TypeScript 使用结构化类型("duck typing"):如果两个类型具有相同的形状,它们就是兼容的,无论其名称或声明位置如何。这与 nominal 类型(Java、C#)形成对比,在名义类型中兼容性取决于声明的类型名称。
ts
interface Point { x: number; y: number; }
function print(: ) { .(p., p.); }
obj = { : , : , : };
(obj);
obj 从未声明为 Point,但仍被接受,因为它在结构上满足形状。传递现有变量时允许额外属性。
为什么这很重要
结构化类型使 TypeScript 灵活且符合人体工程学 — 你可以满足接口而不需要显式实现它,这适合 JavaScript 的对象字面量风格。
权衡:恰好共享一个形状的类型是可互换的,即使在概念上无关(这是人们在需要类似名义的独特性时使用品牌类型的原因)。
超额属性检查异常
ts
print({ x: 1, y: 2, z: 3 }); // ❌ Error: 'z' does not exist in type 'Point'
直接传递的对象字面量会进行更严格的"超额属性检查"以捕捉拼写错误 — 但先将其分配给变量,它就会通过。这是在灵活性和捕捉错误之间的有意平衡。
