一,前言

本篇介绍TS中的重复命名的声明合并

1,声明合并定义
2,接口的声明合并及对接口成员的要求
3,命名空间的声明合并
4,命名空间和函数的声明合并
5,命名空间和类的声明合并
6,命名空间和枚举的声明合并

二,声明合并

声明合并:

编译器会将程序中多个具有相同名称的声明合并为一个声明

优势:

可以将程序中散落在各处的重名声明合并在一起

三,接口的声明合并

接口的声明合并是TS中最常见的一种声明合并
比如,在多个文件中定义同名接口,使用时,会对多个定义同时感知

通过合并避免对接口成员的遗漏

定义两个同名接口,具有不同属性:

interface A {
    x: number
}
interface A {
    y: number
}

这时,两个接口就会合并称成一个接口:

定义变量a为A接口类型,a需要具备两个接口中的所有成员

ts片段合并python ts 合并_命名空间

let a: A = {
    x: 1,
    y: 2
}

在全局模块中,两个接口不在一个文件中也可以发生接口合并

接口的成员-非函数成员:
接口中非函数的成员,需要保证接口成员的唯一性,如果不唯一类型必须相同

在A中重复定义成员y,但类型相同,不报错:

interface A {
    x: number
    y: number	// 在A中重复定义成员y,但类型相同
}
interface A {
    y: number
}

let a: A = {
    x: 1,
    y: 2
}

在A中重复定义成员y,但类型不同,报错:

interface A {
    x: number
    y: string	// 在A中重复定义成员y,但类型不同
}
interface A {
    y: number
}

let a: A = {
    x: 1,
    y: 2
}

ts片段合并python ts 合并_字符串_02

接口的成员-函数成员:
每一个函数都会被声明为一个函数重载

在A接口中定义函数:

interface A {
    x: number
    foo(bar: number):number
}
interface A {
    y: number
    foo(bar: string):string
    foo(bar: number[]):number[]
}
在接口中定义的foo函数,实现了函数重载

实现时,需要指定更为宽泛的类型

let a: A = {
    x: 1,
    y: 2,
    foo(bar: any) {
        return bar
    }
}
函数重载时,我们提到要注意重载函数的声明顺序,
因为函数重载会使用从重载列表中匹配到第一个

接口合并时顺序是如何确定的?

1,接口之内,从上到下

// 1,接口之间,从上到下
interface A {
    y: number
    foo(bar: string):string         // 1
    foo(bar: number[]):number[]     // 2
}

2,接口之间,后面的接口在前

// 2,接口之间,后面的接口在前
interface A {
    x: number
    foo(bar: number):number         // 3
}
interface A {
    y: number
    foo(bar: string):string         // 1
    foo(bar: number[]):number[]     // 2
}

3,例外,如果函数的参数是字符串字面量,会被提升到函数声明的最顶端

// 3,例外,如果函数的参数是字符串字面量,会被提升到函数声明的最顶端
interface A {
    x: number
    foo(bar: number):number         // 5
    foo(bar: 'a'):number            // 2
}
interface A {
    y: number
    foo(bar: string):string         // 3
    foo(bar: number[]):number[]     // 4
    foo(bar: 'b'):number            // 1
}

三,命名空间的声明合并

命名空间的声明合并在上一篇已经涉及到了

注意:

在命名空间中,导出的成员是不能重复定义的

namespace2.ts

// 命名空间
namespace Shape {
    export function square(x: number){
        return x * x
    }
}

namespace.ts

namespace Shape {
    const pi = Math.PI
    // 全局可见
    export function cricle(r: number){
        return pi * r ** 2
    }
    export function square(x: number){	// 重复定义,会报错
        return x * x
    }
}

四,命名空间和函数的声明合并

定义一个函数和同名的命名空间

// 命名空间和函数的声明合并
function Lib() {}
namespace Lib {
    export let version = '1.0'
}
console.log(Lib.version)	// 1.0
这就相当于先声明一个函数,再添加属性

五,命名空间和类的声明合并

声明一个类和同名的命名空间

// 命名空间和类的声明合并
class C {}
namespace C {
    export let state = 1
}
console.log(C.state)    // 1
这就相当于给类添加静态属性

六,命名空间和枚举的声明合并

定义一个枚举和同名的命名空间:

// 命名空间和枚举的声明合并
enum Color {
    Red,
    Yellow,
    Bule
}
namespace Color {
    export function mix() {}
}
相当于为枚举类型添加了方法

ts片段合并python ts 合并_函数重载_03

需要注意:

命名空间在与函数,类进行声明合并时,一定要放在函数,类的定义后面
枚举和命名空间的位置没有要求

七,结尾

在程序中,有多出同名声明其实并不好,最好能封装在模块内
TS照顾了旧工程,如果引入TS,仍能够与老代码共存