声明合并
- 概念引入
- 合并接口
概念引入
“声明合并”是指编译器将针对同一个名字的两个独立声明合并为单一声明。 合并后的声明同时拥有原先两个声明的特性。 任何数量的声明都可被合并;不局限于两个声明
interface Box23 {
height: number;
width: number;
}
interface Box23 {
scale: number;
}
let box: Box23 = {height: 5, width: 6, scale: 10};
上述虽然不会报错,但是不太美观
interface Box23 {
scale: number;
height: number;
width: number;
}
合并接口
最简单也最常见的声明合并类型是接口合并。 从根本上说,合并的机制是把双方的成员放到一个同名的接口里
1、相同接口,同时声明了同名的非函数成员且它们的类型不同,则编译器会报错
相同接口,的非函数的成员应该是唯一的,如果它们不是唯一的,那么它们必须是相同的类型
interface Box23 {
height: number;
width: number;
}
interface Box23 {
scale: number;
width: string
}
// Subsequent property declarations must have the same type. Property 'width' must be of type 'number', but here has type 'string'.
// 随后的属性声明必须具有相同的类型。属性'width'必须是'number'类型,但这里有'string'类型。
2、函数中的接口合并
对于函数成员,每个同名函数声明都会被当成这个函数的一个重载。 同时需要注意,当接口 A与后来的接口 A合并时,后面的接口具有更高的优先级
函数重载回顾一下:
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
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;
}