如何在保留联合结构的同时从TypeScript类型中省略无关属性?
解决TypeScript联合交叉类型中省略固定属性并保留联合结构的问题
问题背景
现有类型定义如下:
type P1 = {prop1: number} type P2 = {prop2: number} type U1 = {u1: string} type U2 = {u2: number} export type Args = P1 & P2 & (U1 | U2)
需要生成一个省略prop1属性的类型CurriedArgs,要求保留原有的联合结构,且不能依赖未导出的子类型(如P1、U1等)。直接使用Omit<Args, 'prop1'>会破坏联合结构,生成不符合预期的交叉类型。
解决方案
使用分布式条件类型实现一个DistributiveOmit工具类型,对联合类型的每个分支单独应用Omit操作,从而保留原有的联合结构:
// 定义分布式Omit工具类型 type DistributiveOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never; // 生成目标类型 type CurriedArgs = DistributiveOmit<Args, 'prop1'>;
代码验证
// 符合预期的取值 const partial1: CurriedArgs = {prop2: 1, u1: ''}; const partial2: CurriedArgs = {prop2: 1, u2: 1}; // 可以正确合并为完整的Args类型 const complete1: Args = {prop1: 42, ...partial1}; const complete2: Args = {prop1: 42, ...partial2}; // 错误示例:不符合联合分支的结构会被TypeScript拦截 // const invalid: CurriedArgs = {prop2: 1, u1: '', u2: 1};
原理说明
- 直接使用
Omit<Args, 'prop1'>时,TypeScript会将Args的联合交叉结构视为整体处理,最终生成(P2 & U1) & (P2 & U2)的交叉类型,要求同时包含u1和u2,不符合需求。 DistributiveOmit利用了TypeScript的分布式条件特性:当T为联合类型时,T extends any会自动将联合拆分为单个成员,对每个成员单独执行Omit<T, K>,最后再将结果重新组合为联合类型,完美保留了原有的分支结构。- 该方案仅依赖已导出的
Args类型,无需引用未导出的子类型,完全满足场景需求。
内容的提问来源于stack exchange,提问作者Nathan Williams
相关产品推荐
相关产品推荐

