TypeScript类型交集处理:移除可选属性的| undefined标识
解决TypeScript类型交集展开后可选属性带
| undefined的问题 问题描述
当合并两个接口的交集类型并展开为对象时,希望可选属性仅显示?: boolean而非?: boolean | undefined:
interface ISelect { selectOnly?: boolean } interface IDefault { defaultValue: string } // 原始交集类型 type BothTypes = ISelect & IDefault
期望鼠标悬停BothTypes时的显示效果:
(alias) type BothTypes = { selectOnly?: boolean; defaultValue: string; }
已尝试方案
使用基础映射类型展开交集,但可选属性会自动带上| undefined:
type Resolve<T> = { [P in keyof T]: T[P] } type BothTypes = Resolve<ISelect & IDefault>
实际得到的结果:
(alias) type BothTypes = { selectOnly?: boolean | undefined; defaultValue: string; }
尝试用Exclude移除undefined也无效:
type Resolve<T> = { [P in keyof T]: Exclude<T[P], undefined> }
解决方案
通过区分类型中的可选键和必选键,分别处理后再合并,可以实现预期效果:
// 提取类型中的可选键 type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T]; // 提取类型中的必选键 type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>; // 自定义Resolve类型,处理可选属性的undefined问题 type Resolve<T> = // 保留必选属性的原始类型 Pick<{ [K in RequiredKeys<T>]: T[K] }, RequiredKeys<T>> & // 处理可选属性:移除undefined并保持可选性 Partial<{ [K in OptionalKeys<T>]: Exclude<T[K], undefined> }> extends infer O ? { [K in keyof O]: O[K] } // 展开合并后的交集为对象 : never;
测试示例
interface ISelect { selectOnly?: boolean } interface IDefault { defaultValue: string } type BothTypes = Resolve<ISelect & IDefault>;
此时鼠标悬停BothTypes,会显示预期的格式:
(alias) type BothTypes = { selectOnly?: boolean; defaultValue: string; }
原理说明
OptionalKeys<T>:通过-?移除可选修饰符后,判断该属性是否能被空对象兼容,以此筛选出原始类型中的可选键。RequiredKeys<T>:从所有键中排除可选键,得到必选键集合。Resolve<T>:将必选属性直接保留,可选属性则通过Partial维持可选性,同时用Exclude<T[K], undefined>移除多余的undefined类型,最后通过类型推断展开交集为扁平对象。
内容的提问来源于stack exchange,提问作者Andrew Allen
相关产品推荐
相关产品推荐

