12、typescript的声明合并

什么是声明合并?

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


接口的声明合并

接口的声明合并是 typescript 中最常见的一种声明合并 比如,在多个文件中定义同名接口,使用时,typescript 会对这多个定义进行合并。

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

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

这时,两个接口就会合并称成一个接口,定义变量a为A接口类型,a需要具备两个接口中的所有成员。

interface A {
  x: number
interface A {
  y: number
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


接口的成员是函数,这个函数可以被重复声明,每一个函数都会被声明为一个函数重载 。

在A接口中定义函数:

interface A {
    x: number
    foo(bar: number):number
interface A {
    y: number
    foo(bar: string):string
    foo(bar: number[]):number[]

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

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,