结构化类型(structural typing)

9 阅读1分钟

结构化类型就是:TypeScript 判断两个类型是否兼容,主要看它们的“结构/成员是否匹配”,而不是看它们的“名字/声明来源”。

一句话:只要“长得像”,就当成同一种类型用。

最直观例子:不看名字,看字段

type User = { id: number; name: string }

const a = { id: 1, name: 'Tom' }
// a 没有显式写成 User,但结构一样,所以可以当 User 用
const u: User = a

有多余字段也通常没问题(但有个例外)

type User = { id: number; name: string }

const a = { id: 1, name: 'Tom', age: 18 }
const u: User = a // 允许:因为至少包含 id/name

例外:对象字面量直接赋值时,会触发“多余属性检查”(为了帮你发现拼写错误):

type User = { id: number; name: string }

const u: User = { id: 1, name: 'Tom', age: 18 } // ❌ 报错:age 多余

解决方式通常是:

  • 先用变量接一下(如上面的 a),或
  • 用更合适的类型(比如把 age 加进类型、或用交叉/扩展),或
  • 少数场景用断言(不推荐滥用)。

为什么 TS 选结构化类型

  • 更贴近 JS 的“鸭子类型”:只要能用(有这些字段/方法),就认为兼容
  • 更利于组合与渐进迁移:你可以逐步给项目加类型,而不用严格继承/实现某个名义类型体系