声明合并(Declaration Merging)是一种独特的 TypeScript 机制,允许将同名的声明合并为一个统一的类型/实体。这适用于接口、命名空间和函数。
interface User { name: string; } interface User { age: number; } const u: User = { name: 'Vasya', age: 42 }; // OK
function helper() {} namespace helper { export function extra() {} } helper.extra(); // OK
如果在接口的不同区间声明了相同名称的方法,并且它们的签名不同,那么合并将如何进行?
答案:
如果在不同的合并接口中声明了同名的方法,TypeScript 会试图在最终接口中“重载”这些方法。然而,如果签名不兼容(无法重载),将导致编译错误。
示例:
interface Foo { bar(a: number): void } interface Foo { bar(a: string): void } // OK: 重载 interface Foo { bar(a: number[]): void } // 错误:不兼容的签名
故事
在一个项目中,通过声明合并扩展了外部接口 Window,以实现不同的功能:一个团队添加了 window.myFeature: boolean,另一个团队添加了 window.myFeature: number。合并引发类型错误,编译器在最终构建时才检测到冲突——有人不得不快速重命名。
故事
因为错误地声明了两个具有不同方法签名的 ArrayHelper 接口,期望它们能够“两个选项都可用”。实际上,第一个签名覆盖了第二个,导致 IDE 中自动补全错误,并在与新模块集成时出现了漏洞。
故事
通过声明合并使用命名空间“扩展”函数时,开发者错误地在命名空间内声明了 export,导致函数不可用。直到代码审查后才发现,没有正确的 export 合并是无法工作的,属性不会出现在函数上。