介绍
指编译器将针对同一个名字的两个独立声明合并为单一声明,合并后的声明同时拥有原先两个声明的特性
注:任何数量的声明都可被合并
// 两个相同的接口会进行合并
interface Box {
height: number;
width: number;
}
interface Box {
scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};
console.log(box)
TS的声明会创建以下三种实体之一:
- 命名空间:会创建一个新的命名空间,他包含了用(.)符号来访问时使用的名字
- 类型:用声明的模型创建一个类型并绑定到给定的名字上
- 值:会创建在JS输出中看到的值
合并接口:最简单也是最常见的合并类型是接口合并,合并机制是:把双方的成员放到一个同名的接口里
注意事项:
- 接口的非函数成员应该是唯一的,如果不是唯一的那么他们必须是相同的类型,否则会报错
- 对于函数成员,每个同名函数声明都会被当成这个函数的一个重载,注:同名接口后面的接口具有更高的优先级
// 同名接口后面的接口具有更高的优先级
interface Animal {}
interface Sheep {}
interface Dog {}
interface Cat {}
interface Cloner {
clone(animal: Animal): Animal;
}
interface Cloner {
clone(animal: Sheep): Sheep;
}
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}
// 合并后
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Sheep): Sheep;
clone(animal: Animal): Animal;
}
例外:当出现特殊的函数签名时,如果签名里有一个参数的类型是单一的字符串字面量,那么他将被提升到重载列表的最顶端
// 例外
interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: 'div'): HTMLDivElement;
createElement(tagName: 'span'): HTMLSpanElement;
}
interface Document {
createElement(tagName: string): HTMLElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
}
// 合并后
interface Document {
createElement(tagName: "canvas"): HTMLCanvasElement;
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}
合并命名空间
与接口相似,同名的命名空间也会合并其成员
- 对于命名空间的合并,模块导出的同名接口进行合并,构成单一命名空间内含合并后的接口
- 对于命名空间值得合并,如果当前已经存在给定名字的命名空间,那么后来的命名空间的导出成员会被加到已经存在的那个模块里
- 对于非导出成员的合并,合并后从其他命名空间合并进来的成员无法访问非导出成员
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 clasas Dog { }
}
// 对于非导出成员
namespace Animal {
let haveMuscles = true;
export function animalsHaveMuscles() {
return haveMuscles;
}
}
// doAnimalsHaveMuscles函数虽是合并命名空间的一部分,但是访问不了未导出的成员
namespace Animal {
export function doAnimalsHaveMuscles() {
// return haveMuscles; // Error, because haveMuscles is not accessible here
}
}