TypeScript如何实现支持点表示法的嵌套Pick泛型工具
点表示法实现嵌套对象属性Pick类型
完全可以实现支持单路径、多路径联合入参的嵌套属性Pick工具类型。
基础示例
单路径使用场景:
interface Test { customer: { email: string; name: { firstName: string; }; }; }; type PickedTest = PickByDotNotation<Test, "customer.name.firstName">; // 类型等价于 { customer: { name: { firstName: string } } }
多路径联合使用场景:
type PickedTest = PickByDotNotation<Test, "customer.name.firstName" | "customer.email">; // 类型等价于 { customer: { name: { firstName: string }, email: string } }
完整实现代码
// 按点分隔符拆分路径为字符串元组 type SplitPath<PathStr extends string> = PathStr extends `${infer Head}.${infer Rest}` ? [Head, ...SplitPath<Rest>] : [PathStr]; // 联合类型转交叉类型,用于合并多路径生成的独立对象结构 type UnionToIntersection<Union> = (Union extends unknown ? (arg: Union) => void : never) extends (arg: infer Intersection) => void ? Intersection : never; // 根据拆分后的路径元组,递归生成对应的嵌套对象结构 type BuildNestedObj<T, PathTuple extends PropertyKey[]> = PathTuple extends [infer FirstKey extends keyof T, ...infer RestKeys extends PropertyKey[]] ? RestKeys extends [] ? { [K in FirstKey]: T[K] } : { [K in FirstKey]: BuildNestedObj<T[K], RestKeys> } : never; // 对外暴露的主工具类型 type PickByDotNotation<T, Paths extends string> = // 利用分布式条件类型遍历联合类型中的每一条路径 UnionToIntersection<Paths extends unknown ? BuildNestedObj<T, SplitPath<Paths>> : never> extends infer Result ? { [K in keyof Result]: Result[K] } : never;
效果验证
interface Demo { customer: { email: string; age: number; name: { firstName: string; lastName: string; }; }; order: { id: string; payTime: Date; }; } // 多路径测试 type DemoPicked = PickByDotNotation<Demo, "customer.name.firstName" | "customer.email" | "order.id">; /* 输出类型等价于: { customer: { name: { firstName: string; }; email: string; }; order: { id: string; }; } */
内容的提问来源于stack exchange,提问作者czlowiek488
相关产品推荐
相关产品推荐

