TypeScript如何定义元素仅匹配多个指定类型之一的数组
问题原因
TypeScript 采用结构类型系统,默认的联合类型 A | B 只要求对象满足其中一个类型的结构约束,允许额外存在另一个类型的属性,所以你定义的 C[] 可以接收同时包含A、B属性的混合对象,不符合你的预期。
解决方案:使用互斥联合类型
你可以通过自定义工具类型实现严格的互斥联合,保证数组元素只能完全匹配其中一个类型,不能同时包含多个类型的属性。
方案1:双类型互斥(XOR实现)
适合只有两个可选类型的场景:
首先定义两个工具类型:
// 实现:属于T但不属于U的属性全部设为可选never type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never } // 互斥类型:只能满足T或U其中一个,不能同时满足 type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T)
然后替换你的C类型定义:
interface A { m: string, n: number } interface B { x: boolean y: number[] } // 替换原来的联合类型为互斥类型 type C = XOR<A, B>
此时测试赋值:
// 正常通过 const arr1: C[] = [ {m: '1', n: 1} ] // 正常通过 const arr2: C[] = [ {x: true, y: [1,2,3]} ] // 报错:不能同时存在A和B的属性 const arr3: C[] = [ {m: '1', n: 1, x: true} ]
方案2:多类型通用严格联合
如果后续需要扩展更多可选类型,可以用通用的严格联合工具类型:
type StrictUnionHelper<T, All> = T extends any ? T & Partial<Record<Exclude<keyof All, keyof T>, never>> : never type StrictUnion<T> = StrictUnionHelper<T, T>
使用方式:
// 支持任意数量的类型联合 type C = StrictUnion<A | B> // 扩展多类型示例:type C = StrictUnion<A | B | D | E>
效果和双类型互斥一致,同时支持更多联合成员。
内容的提问来源于stack exchange,提问作者JianCheng.Kang
相关产品推荐
相关产品推荐

