TypeScript DeepOmit类型工具单属性可用,多属性失效问题求助
实现支持点语法与联合路径的DeepOmit类型工具
问题分析
你当前的DeepOmit实现仅能处理单个属性路径,当传入多个路径的联合类型时,由于TypeScript条件类型的分发特性,无法正确聚合所有路径的省略操作,导致结果不符合预期。
解决方案
核心思路是将联合路径拆分为单个路径逐个处理,再通过交叉类型合并所有省略结果,实现同时移除多个深层属性的效果。
完整实现代码
// 将联合类型转换为交叉类型,用于合并多次DeepOmit的结果 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // 处理单个深层路径的省略逻辑 type DeepOmitSingle<T, Path extends string> = T extends object ? Path extends `${infer Key}.${infer Rest}` ? { // 遍历对象的每个键 [K in keyof T]: K extends Key // 如果当前键匹配路径的第一部分,递归处理剩余路径 ? DeepOmitSingle<T[K], Rest> // 不匹配则保留原类型 : T[K] } // 路径无嵌套时,直接使用Omit移除顶层属性 : Omit<T, Path> // 非对象类型直接返回原类型 : T; // 对外暴露的DeepOmit,支持单个或联合路径 type DeepOmit<T, Paths extends string> = UnionToIntersection< Paths extends string ? DeepOmitSingle<T, Paths> : never >;
测试验证
type Input = { a: string; b: { c: string; d: string; e: string; }; }; // 测试单个路径 type OmitedSingle = DeepOmit<Input, "b.c">; // 结果:{ a: string; b: { d: string; e: string } } // 测试联合路径 type OmitedUnion = DeepOmit<Input, "b.c" | "b.d">; // 结果:{ a: string; b: { e: string } }
实现说明
- UnionToIntersection:将联合类型转换为交叉类型,确保多个路径的省略操作是"同时生效"而非"二选一"。
- DeepOmitSingle:专注处理单个深层路径,通过模板字符串直接拆分路径的层级,递归处理嵌套对象,无需额外的数组转换逻辑,比原实现更简洁高效。
- DeepOmit:对传入的联合路径进行分发处理,每个路径单独执行
DeepOmitSingle后,通过UnionToIntersection合并结果,最终得到所有路径都被省略后的类型。
原实现优化建议
- 移除不必要的
UnDot、Dot、Tail辅助类型,直接使用模板字符串拆分路径,减少类型计算的复杂度。 - 利用联合转交叉的方式处理多路径场景,避免条件类型分发导致的逻辑错误。
内容的提问来源于stack exchange,提问作者Caique Camargo
相关产品推荐
相关产品推荐

