TypeScript中接口的扩展类型与交叉类型是否等价?
为什么Equal<ExtendedType, IntersectionType>返回false
你使用的Equal是TS生态中常用的严格类型全等判断工具,它的判断逻辑不仅校验结构的互相兼容性,还会区分类型的核心身份属性:
ExtendedType是标准的接口类型,属于TS内置的接口实体,支持声明合并特性IntersectionType是多个接口交叉运算得到的计算类型,属于类型别名的派生结果,不支持声明合并特性
二者的结构完全互相兼容,所以你给变量赋值时的缺失属性提示完全一致。如果仅需要判断结构等价,可以用如下写法,返回结果为true:
type CheckStructEqual = ExtendedType extends IntersectionType ? IntersectionType extends ExtendedType ? true : false : false
接口扩展与交叉类型的核心差异
1. 同名属性冲突的处理逻辑不同
interface extends会在定义阶段就校验多个父接口的同名属性兼容性,一旦类型不兼容直接抛出错误,提前发现问题- 交叉类型不会在定义阶段校验冲突,会自动将冲突属性的类型合并为
never,只有实际使用该属性时才会报错
示例:
interface A { id: string } interface B { id: number } // 定义阶段直接报错:父接口属性id类型不兼容 interface C extends A, B {} // 定义阶段无报错 type D = A & B const d: D = {id: '123'} // 赋值时才会报错,id的类型为never
2. 声明合并支持不同
接口支持多次同名声明自动合并,交叉类型作为type别名不允许重复声明:
// 合法,会和之前定义的ExtendedType合并,新增extra属性 interface ExtendedType { extra: string } // 报错:标识符IntersectionType重复声明 type IntersectionType = {extra: string}
3. 适用场景不同
- 优先用
interface extends的场景:需要定义可复用的复合类型、需要后续扩展声明、希望在定义阶段就发现属性冲突问题 - 必须用交叉类型的场景:临时合并类型不需要复用、需要合并非接口类型(比如函数类型、联合类型、原始类型),示例:
// 给函数类型追加属性,只能用交叉类型实现 type FuncWithMeta = (() => number) & { version: string author: string }
内容的提问来源于stack exchange,提问作者Subrato Pattanaik
相关产品推荐
相关产品推荐

