TypeScript 声明合并
TypeScript 编译器会将程序中多个具有 相同名称 的声明合并为一个声明。
但这并不是说 TypeScript 会随意的合并两个名称相同的字符串变量,这显然是不符合语法规定的,那么本节将介绍什么样的声明可以进行合并。
1. 慕课解释
TypeScript 中的声明会创建以下三种实体之一:命名空间、类型或值。
来看以下声明都创建了什么实体:
声明类型 | 创建了命名空间 | 创建了类型 | 创建了值 |
---|---|---|---|
Namespace | √ | √ | |
Class | √ | √ | |
Enum | √ | √ | |
Interface | √ | ||
Type Alias | √ | ||
Function | √ | ||
Variable | √ |
2. 合并接口
最简单也最常见的声明合并类型是接口合并。
interface Box {
height: number
width: number
}
interface Box {
scale: number
width: number // 类型相同 OK
}
let box: Box = {height: 5, width: 6, scale: 10}
接口合并,则接口的 非函数的成员须是唯一的,哪怕不唯一,最起码也要类型相同 。但如果类型不同,则编辑器报错。
对于函数成员,每个同名函数声明都会被当成 这个函数的一个重载 ,后面的接口具有更高优先级。
接口合并时,将遵循以下规范:
- 接口内优先级是从上到下;
- 后面的接口具有更高优先级;
-
如果函数的参数是字符串字面量,会被提升到函数声明的最顶端。
interface Document { createElement(tagName: any): Element // 5 } interface Document { createElement(tagName: 'div'): HTMLDivElement // 2 createElement(tagName: 'span'): HTMLSpanElement // 3 } interface Document { createElement(tagName: string): HTMLElement // 4 createElement(tagName: 'canvas'): HTMLCanvasElement // 1 }
按照上面介绍的规则,得到合并后的声明:
interface Document {
createElement(tagName: 'canvas'): HTMLCanvasElement
createElement(tagName: 'div'): HTMLDivElement
createElement(tagName: 'span'): HTMLSpanElement
createElement(tagName: string): HTMLElement
createElement(tagName: any): Element
}
3. 合并命名空间
合并多个具有相同名称的命名空间:
- 导出成员不可重复定义
-
非导出成员仅在其原有的(合并前的)命名空间内可见
namespace A { let used = true
export function fn() { return used } }
namespace A { export function fnOther() { return used // Error, 未找到变量 used } }
A.fn() // OK A.fnOther() // OK
代码解释:
第一个命名空间内的非导出成员 used
仅在第一个命名空间内可见。 命名空间对象 A
可以分别访问在第一个或第二个声明的导出成员。
4. 命名空间与其它类型的合并
只要命名空间的定义符合将要合并类型的定义,命名空间就可以与其它类型的声明进行合并,合并结果包含两者的声明类型。
4.1 命名空间与类的合并
合并名称相同的命名空间与类:
- 命名空间内的成员必须导出,合并后的类才能访问
- 命名空间内导出的成员,相当于合并后类的静态属性
- 命名空间要放在类的定义后面
注意: 命名空间要放在类的定义后面,命名空间内导出的成员,相当于合并后类的静态属性。
4.2 命名空间与函数的合并
- 名称相同的命名空间与函数挂载同一个对象
- 命名空间要放在函数的定义后面
命名空间和函数可以进行合并,是因为在 JavaScript 中函数也是对象。
4.3 命名空间与枚举的合并
命名空间可以用来扩展枚举型:
解释: 枚举本身也是个对象,与命名空间对象合并后对象的属性进行了扩充。
5. 小结
虽然 TypeScript 有声明合并的功能,但是在工作中应尽量避免定义命名相同的声明,合理使用模块来规避这类情况。
访问者可将本网站提供的内容或服务用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯本网站及相关权利人的合法权利。
本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站,邮箱:80764001@qq.com,予以删除。