为什么TypeScript中交叉类型的值可直接赋值给其成员类型?
TypeScript 交叉类型赋值合法的底层原因
首先是相关代码示例:
type A = {a: number}; type B = {b: boolean, c: number}; type I = A & B; let aAndB: I = { a: 1, b: true, c: 2 } let valueOfA: A = aAndB; // No Error Here!!!
这类赋值合法的底层原因如下:
- TypeScript 采用结构类型系统(鸭子类型)
TypeScript判断类型兼容性的核心逻辑是:只要待赋值的值的结构完全满足目标类型的所有约束,就可以完成赋值,不需要两个类型存在名义上的继承、关联声明。
本案例中目标类型A仅要求值存在number类型的a属性,而aAndB完全符合该要求,因此满足兼容条件。 - 交叉类型天然是所有参与交叉类型的子类型
A & B的语义是该类型的值需要同时符合A、B两个类型的所有约束,因此所有A & B类型的实例,必然是A类型的合法实例,也必然是B类型的合法实例,属于A和B的子类型。
类型系统的通用规则就是子类型的值可以直接赋值给父类型的变量,不会触发类型错误。
额外说明:如果直接写let valueOfA: A = {a:1, b:true, c:2}会触发多余属性校验错误,这是TypeScript针对新鲜对象字面量做的额外语法校验,避免开发者误写多余属性,不属于通用的类型兼容性规则,当赋值源是已经经过类型校验的非字面量变量时,这条额外校验不会生效。
内容的提问来源于stack exchange,提问作者Ashutosh Biswas
相关产品推荐
相关产品推荐

