如何在TypeScript中区分包含多判别值成员的联合类型?
解决含多判别值的联合类型筛选问题
你定义的联合类型包含了带有多个判别值的Simple接口和独立的Complex接口,但现有DiscriminateUnion工具类型无法正确筛选出带有'bar'判别值的Simple类型,返回了never。原代码如下:
interface Simple { type: 'foo' | 'bar'; field: string; } interface Complex { type: 'quux'; whoa: string; so: string; many: string; fields: string; } type All = Simple | Complex; type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T extends Record<K, V> ? T : never; // 符合预期:Complex type t1 = DiscriminateUnion<All, 'type', 'quux'>; // 结果为never :( type t2 = DiscriminateUnion<All, 'type', 'bar'>;
问题根源
原工具类型使用Record<K, V>做判断,要求目标类型的K字段完全等于V。但Simple的type是'foo' | 'bar',并不等于单一值'bar',所以被判定为不符合条件,返回never。
修改后的工具类型
我们需要调整逻辑,判断传入的V是否是目标类型K字段的子集,而非要求完全相等。修改后的类型工具如下:
type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T extends { [P in K]: infer U } ? V extends U ? T : never : never;
验证效果
用修改后的类型测试:
// 结果为Simple,符合预期 type t2 = DiscriminateUnion<All, 'type', 'bar'>; // 结果同样为Simple type t3 = DiscriminateUnion<All, 'type', 'foo'>; // 结果为Complex,符合预期 type t1 = DiscriminateUnion<All, 'type', 'quux'>;
逻辑说明
- 通过
T extends { [P in K]: infer U }提取联合类型中每个成员的K字段类型,保存到U - 判断传入的筛选值
V是否是U的子集(V extends U) - 满足条件则保留该类型成员,否则返回
never
这样既不用拆分Simple接口,也能正确筛选出包含目标判别值的类型。
内容的提问来源于stack exchange,提问作者skelley
相关产品推荐
相关产品推荐

