Skip to content

声明合并

声明合并(Declaration Merging)是 TypeScript 中的一项特性,它允许你将多个同名的声明合并为一个声明。这在扩展现有的类型或接口时非常有用,可以让你安全地添加新的成员而不破坏原有的代码结构。TypeScript 支持几种不同类型的声明合并,主要包括接口合并和命名空间合并。

接口合并(Interface Merging)

接口合并是最常见的声明合并形式。当你有多个同名的接口定义时,TypeScript 会自动将它们合并为一个接口,其中包含所有这些接口中定义的成员。

示例:合并接口

typescript
interface Box {
  height: number;
}

interface Box {
  width: number;
}

// 合并后的 Box 接口相当于:
// interface Box {
//   height: number;
//   width: number;
// }

接口合并不仅可以添加新的属性,还可以添加方法:

typescript
interface Box {
  getHeight(): number;
}

interface Box {
  getWidth(): number;
}

// 现在 Box 包含两个方法

注意事项

  • 不能合并类:尽管接口可以合并,但类不行。如果你尝试创建两个同名的类,TypeScript 会报错。
  • 成员冲突:如果两个接口中有相同名称但不兼容的成员(例如,相同名称但不同类型的属性),则会导致编译错误。

命名空间合并(Namespace Merging)

命名空间合并允许你在一个命名空间中添加额外的变量、函数或类等。这对于组织代码和扩展现有库特别有用。

示例:合并命名空间

typescript
namespace Validation {
  export interface StringValidator {
    isAcceptable(s: string): boolean;
  }
}

namespace Validation {
  const lettersRegexp = /^[A-Za-z]+$/;

  export class LettersOnlyValidator implements StringValidator {
    isAcceptable(s: string) {
      return lettersRegexp.test(s);
    }
  }
}

// Validation 命名空间现在包含了接口和类

函数与命名空间的合并

TypeScript 还支持一种特殊的合并方式,即函数声明和实现可以在同一个命名空间内合并。这种模式下,你可以先声明一个函数,然后在同一命名空间中提供其实现,并且可以在这个命名空间中添加额外的属性或方法。

示例:函数与命名空间合并

typescript
function buildLabel(name: string): string {
  return "Hello, " + name;
}

namespace buildLabel {
  export function preprend(prefix: string, name: string): string {
    return prefix + ", " + name;
  }
}

buildLabel("Sam"); // 使用原始函数
buildLabel.preprend("Mr.", "Sam"); // 使用命名空间中的附加功能

类与命名空间的合并

类似地,TypeScript 允许你合并类和命名空间,以便在类外部添加静态成员(如静态方法或属性)。这有助于保持类的简洁,同时仍然能够提供额外的功能。

示例:类与命名空间合并

typescript
class Grid {
  static origin = { x: 0, y: 0 };
  scale(value: number) {
    console.log(value);
  }
}

namespace Grid {
  export function calculateDistanceFromOrigin(point: { x: number; y: number }) {
    let xDist = point.x - Grid.origin.x;
    let yDist = point.y - Grid.origin.y;
    return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
  }
}

总结

声明合并是 TypeScript 提供的一个强大工具,它使得我们可以灵活地扩展现有类型而不需要修改原始代码。无论是接口、命名空间还是函数和类,声明合并都为我们提供了极大的便利,特别是在需要扩展第三方库或者组织大型项目时。正确使用声明合并可以提高代码的可维护性和复用性,但也要注意避免过度使用,以免引入不必要的复杂性。

Released under the MIT License.