TypeScript中Interface与Type的属性值交并集疑问解析
TypeScript交叉类型与联合类型疑惑解答
1. 交叉类型Person & Lifespan为何不是never?取值是什么?
先明确前提:假设我们定义的两个接口无冲突属性(无同名但类型不兼容的字段),比如:
interface Person { name: string; age: number; } interface Lifespan { birth: Date; death?: Date; }
为什么不是never类型?
never是没有任何值能满足的类型,而交叉类型&的本质是取两个类型「值的集合的交集」——不是合并接口属性后找冲突,而是看是否存在值能同时符合两个类型的要求。只要两个类型的取值集合有重叠(存在同时满足两个接口的对象),交叉类型就不会是never。
只有当两个类型存在同名且类型不兼容的属性时,交叉类型才会变成never。比如Person的age是number,Lifespan的age是string,交叉后age的类型是number & string(没有值能同时是数字和字符串),整个交叉类型就会是never。
该类型的取值是什么?
所有同时具备两个接口所有必填属性的对象,还可包含可选属性。比如:
const validExample: Person & Lifespan = { name: "Alice", age: 30, birth: new Date(1993, 0, 1), death: new Date(2093, 0, 1) // 可选字段可加可不加 };
怎么理解“类型操作针对值的集合而非接口属性”?
把每个TypeScript类型看成一个“池子”:
Person池子里装着所有有name(字符串)和age(数字)的对象Lifespan池子里装着所有有birth(Date)、可选death(Date)的对象
类型操作(如&或|)直接对这些“池子”做集合运算,而非修改接口定义。交叉类型&就是取两个池子的重叠部分——同时在两个池子里的对象,也就是同时符合两个接口的对象;不是把两个接口的属性拼在一起后检查冲突(除非属性本身类型冲突)。
2. 联合类型Person | Lifespan的可赋值取值有哪些?
联合类型|是取两个类型「值的集合的并集」,只要符合其中一个接口的要求即可,具体分三类:
- 仅符合
Person的对象:有name和age字段,不需要birth或death,比如:const onlyPerson: Person | Lifespan = { name: "Bob", age: 25 }; - 仅符合
Lifespan的对象:有birth字段,可选death,不需要name或age,比如:const onlyLifespan: Person | Lifespan = { birth: new Date(2000, 5, 10) }; - 同时符合两个接口的对象:也就是前面交叉类型里的取值,也可以赋值给联合类型(因为它同时满足两个类型,自然属于并集的一部分),比如之前的
validExample也能赋值给Person | Lifespan。
内容的提问来源于stack exchange,提问作者Deen John
相关产品推荐
相关产品推荐

