34.【TypeScript 教程】声明合并

简介: 34.【TypeScript 教程】声明合并

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 命名空间与类的合并

合并名称相同的命名空间与类:

  • 命名空间内的成员必须导出,合并后的类才能访问
  • 命名空间内导出的成员,相当于合并后类的静态属性
  • 命名空间要放在类的定义后面

实例演示

class Album {
  label!: Album.AlbumLabel
}
namespace Album {
  export class AlbumLabel { }
  export const num = 10
}
 
console.log(Album.num) // 10

注意: 命名空间要放在类的定义后面,命名空间内导出的成员,相当于合并后类的静态属性。

4.2 命名空间与函数的合并

  • 名称相同的命名空间与函数挂载同一个对象
  • 命名空间要放在函数的定义后面

实例演示

function buildLabel(name: string): string {
  return buildLabel.prefix + name + buildLabel.suffix
}
 
namespace buildLabel {
  export let suffix = '.C'
  export let prefix = 'Hello, '
}
 
console.log(buildLabel('Mr.Pioneer')) // Hello, Mr.Pioneer.C

命名空间和函数可以进行合并,是因为在 JavaScript 中函数也是对象。

4.3 命名空间与枚举的合并

命名空间可以用来扩展枚举型:

实例演示

enum Color {
  red = 1,
  green = 2,
  blue = 4
}
 
namespace Color {
  export function mixColor(colorName: string) {
    switch (colorName) {
      case 'yellow':
        return Color.red + Color.green
      case 'white':
        return Color.red + Color.green + Color.blue
      default:
        break
    }
  }
}
 
console.log(Color.mixColor('yellow')) // 3

解释: 枚举本身也是个对象,与命名空间对象合并后对象的属性进行了扩充。

5. 小结

虽然 TypeScript 有声明合并的功能,但是在工作中应尽量避免定义命名相同的声明,合理使用模块来规避这类情况。

相关文章
|
1月前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
1月前
|
JavaScript 前端开发 Java
TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第10天】TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
1月前
|
JavaScript 前端开发 安全
TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
1月前
|
JavaScript 索引
TypeScript(TS)安装指南与基础教程学习全攻略(二)
TypeScript(TS)安装指南与基础教程学习全攻略(二)
52 0
|
1月前
|
JavaScript 前端开发 安全
TypeScript(TS)安装指南与基础教程学习全攻略(一)
TypeScript(TS)安装指南与基础教程学习全攻略(一)
29 0
|
3月前
|
JavaScript 前端开发 编译器
TypeScript教程(一)在vscode中的配置TypeScript环境
本文是一篇TypeScript入门教程,介绍了在VS Code中配置TypeScript环境的步骤,包括安装Node.js、使用npm安装TypeScript、配置npm镜像源、安装VS Code的TypeScript扩展,以及创建和运行一个简单的TypeScript "Hello World"程序。
TypeScript教程(一)在vscode中的配置TypeScript环境
|
3月前
|
资源调度 JavaScript 前端开发
TypeScript实战教程(一):表单上传与后端处理
本文是TypeScript实战教程的第一部分,介绍了使用TypeScript进行表单上传和后端处理的完整流程,包括环境配置、前端表单创建、使用TypeScript和Express框架搭建服务端、处理表单数据,并提供了详细的代码示例和运行测试方法。
TypeScript实战教程(一):表单上传与后端处理
|
4月前
|
JavaScript 前端开发 程序员
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
79 0
|
5月前
|
JavaScript Java API
30.【TypeScript 教程】Reflect Metadata
30.【TypeScript 教程】Reflect Metadata
116 4
|
5月前
|
JavaScript 编译器
31.【TypeScript 教程】混入(Mixins)
31.【TypeScript 教程】混入(Mixins)
40 3