版权

文章转载自:https://github.com/zhongsp

建议您直接跳转到上面的网址查看最新版本。

介绍

TypeScript有一些独特的概念,有的是因为我们需要描述JavaScript顶级对象的类型发生了哪些变化。 这其中之一叫做声明合并。 理解了这个概念,对于你使用TypeScript去操作现有的JavaScript来说是大有帮助的。 同时,也会有助于理解更多高级抽象的概念。

首先,在了解如何进行声明合并之前,让我们先看一下什么叫做声明合并

在这个手册里,声明合并是指编译器会把两个相同名字的声明合并成一个单独的声明。 合并后的声明同时具有那两个被合并的声明的特性。 声明合并不限于只合并两个,任意数量都可以。

基础概念

Typescript中的声明会创建以下三种实体之一:命名空间,类型或者值。 用于创建命名空间的声明会新建一个命名空间:它包含了可以用(.)符号访问的一些名字。 用于创建类型的声明所做的是:用给定的名字和结构创建一种类型。 最后,创建值的声明就是那些可以在生成的JavaScript里看到的那部分(比如:函数和变量)。

Declaration Type Namespace Type Value
Namespace X   X
Class   X X
Interface   X  
Function     X
Variable     X

理解每个声明创建了什么,有助于理解当声明合并时什么东西被合并了。

理解了每种声明会对应创建什么对于理解如果进行声明合并是有帮助的。

合并接口

最简单最常见的就是合并接口,声明合并的种类是:接口合并。 从根本上说,合并的机制是把各自声明里的成员放进一个同名的单一接口里。

interface Box {
height: number;
width: number;
} interface Box {
scale: number;
} var box: Box = {height: 5, width: 6, scale: 10};

接口中非函数的成员必须是唯一的。如果多个接口中具有相同名字的非函数成员就会报错。

对于函数成员,每个同名函数声明都会被当成这个函数的一个重载。

需要注意的是,接口A与它后面的接口A(把这个接口叫做A')合并时,A'中的重载函数具有更高的优先级。

如下例所示:

interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: string): HTMLElement;
}
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
}

这三个接口合并成一个声明。 注意每组接口里的声明顺序保持不变,只是靠后的接口会出现在它前面的接口声明之前。

interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}

合并命名空间

与接口相似,同名的命名空间也会合并其成员。 命名空间会创建出命名空间和值,我们需要知道这两者都是怎么合并的。

命名空间的合并,模块导出的同名接口进行合并,构成单一命名空间内含合并后的接口。

值的合并,如果当前已经存在给定名字的命名空间,那么后来的命名空间的导出成员会被加到已经存在的那个模块里。

Animals声明合并示例:

namespace Animals {
export class Zebra { }
} namespace Animals {
export interface Legged { numberOfLegs: number; }
export class Dog { }
}

等同于:

namespace Animals {
export interface Legged { numberOfLegs: number; } export class Zebra { }
export class Dog { }
}

除了这些合并外,你还需要了解非导出成员是如何处理的。 非导出成员仅在其原始存在于的命名空间(未合并的)之内可见。这就是说合并之后,从其它命名空间合并进来的成员无法访问非导出成员了。

下例提供了更清晰的说明:

namespace Animal {
var haveMuscles = true; export function animalsHaveMuscles() {
return haveMuscles;
}
} namespace Animal {
export function doAnimalsHaveMuscles() {
return haveMuscles; // <-- error, haveMuscles is not visible here
}
}

因为haveMuscles并没有导出,只有animalsHaveMuscles函数共享了原始未合并的命名空间可以访问这个变量。 doAnimalsHaveMuscles函数虽是合并命名空间的一部分,但是访问不了未导出的成员。

命名空间与类和函数和枚举类型合并

命名空间可以与其它类型的声明进行合并。 只要命名空间的定义符合将要合并类型的定义。合并结果包含两者的声明类型。 Typescript使用这个功能去实现一些JavaScript里的设计模式。

首先,尝试将命名空间和类合并。 这让我们可以定义内部类。

class Album {
label: Album.AlbumLabel;
}
namespace Album {
export class AlbumLabel { }
}

合并规则与上面合并命名空间小节里讲的规则一致,我们必须导出AlbumLabel类,好让合并的类能访问。 合并结果是一个类并带有一个内部类。 你也可以使用命名空间为类增加一些静态属性。

除了内部类的模式,你在JavaScript里,创建一个函数稍后扩展它增加一些属性也是很常见的。 Typescript使用声明合并来达到这个目的并保证类型安全。

function buildLabel(name: string): string {
return buildLabel.prefix + name + buildLabel.suffix;
} namespace buildLabel {
export var suffix = "";
export var prefix = "Hello, ";
} alert(buildLabel("Sam Smith"));

相似的,命名空间可以用来扩展枚举型:

enum Color {
red = 1,
green = 2,
blue = 4
} namespace Color {
export function mixColor(colorName: string) {
if (colorName == "yellow") {
return Color.red + Color.green;
}
else if (colorName == "white") {
return Color.red + Color.green + Color.blue;
}
else if (colorName == "magenta") {
return Color.red + Color.blue;
}
else if (colorName == "cyan") {
return Color.green + Color.blue;
}
}
}

非法的合并

并不是所有的合并都被允许。 现在,类不能与类合并,变量与类型不能合并,接口与类不能合并。 想要模仿类的合并,请参考Mixins in TypeScript

转载:《TypeScript 中文入门教程》 11、声明合并的更多相关文章

  1. 转载:TypeScript 简介与《TypeScript 中文入门教程》

    简介 TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程.安德斯·海尔斯伯格,C#的首席架构 ...

  2. 转载:《TypeScript 中文入门教程》

    缘由 事情是这样的,我想搜索 TypeScript 中文教程,结果在 https://www.baidu.com , https://cn.bing.com ,上都找不到官方的翻译,也没有一个像样的翻 ...

  3. 【转】TypeScript中文入门教程

    目录 虽然我是转载的,但看在Copy这么多文章也是很幸苦的好吧,我罗列一个目录. 转载:<TypeScript 中文入门教程> 17.注解 (2015-12-03 11:36) 转载:&l ...

  4. 《TypeScript 中文入门教程》

    转载:<TypeScript 中文入门教程> 17.注解 (2015-12-03 11:36) 转载:<TypeScript 中文入门教程> 16.Symbols (2015- ...

  5. 转载:《TypeScript 中文入门教程》 14、输入.d.ts文件

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 当使用外部JavaScript库或新的宿主API时,你需要一个声明文件(.d.t ...

  6. 转载:《TypeScript 中文入门教程》 7、模块

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...

  7. 转载:《TypeScript 中文入门教程》 5、命名空间和模块

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...

  8. 转载:《TypeScript 中文入门教程》 4、类

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但这对 ...

  9. 转载:《TypeScript 中文入门教程》 17、注解

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 随着TypeScript和ES6里引入了类,现在在一些场景下我们会需要额外的特性 ...

随机推荐

  1. 程序员眼中的 SQL Server-执行计划教会我如何创建索引?

    先说点废话 以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫 ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6  获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 ...

  3. spring官网下载

    1.第一步:打开官网:http://projects.spring.io/ 2.第二步:点击“SPRING FRAMEWORK”图片 3.第三步:点击“小猫”图标 4.第四步:拉到页面中部的位置,找到 ...

  4. Objective-C 观察者模式--简单介绍和使用

    观察者模式(有时又被称为发布-订阅模式) 在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知. 这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实 ...

  5. angularjs 2.0 快速案例(1)

    前言 上一节我们已经把环境给搭建起来了,现在我们通过一个快速案例把angular 2.0 初步了解一下,后续我们会深入每一个细节,这个案例主要是一个[英雄(Hero)]列表的展示,创建,编辑.这个案例 ...

  6. 30个你必须记住的CSS选择符

    所以你学会了基础的id,类和后代选择符,然后你就一直用它们了吗?如果是这样,你丢失了(css的)巨大的灵活性.在本文中提到的很多选择器属于CSS3规范的一部分,因此,只有在现代浏览器中才可使用. 1. ...

  7. Spring声明式事务管理

    一.Spring 的声明式事务管理概述 1.Spring 的声明式事务管理在底层是建立在 AOP 的基础之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法 ...

  8. iOS中通讯录的开发

    通讯录开发主要是获取用户手机中的联系人,进而可以在应用中添加好友 一 .如何访问通讯录 (1)在iOS9之前,有两个框架可以访问用户的通讯录 AddressBookUI.framework: 提供了联 ...

  9. LINQ系列:Linq to Object相等操作符

    相等操作符通过比较两个序列来检查它们相应的元素是否相同.如果两个序列有相同的元素,并且对应元素的值相同,则认为这两个序列是相等的. SequenceEqual操作符判定两个集合是否相等.判定是通过并行 ...

  10. ClickOnce部署(1):一些发布方式

    ClickOnce是什么玩意儿,这个问题嘛,在21世纪的互联网严重发达的时代,估计也没有必要大费奏章去介绍了,弄不好的话,还有抄袭之嫌.因此,有关ClickOnce的介绍,各位朋友可以直接查找MSDN ...