TypeScript按点语法批量选取对象属性的类型定义求助
解决嵌套属性批量选取的TypeScript类型定义及函数标注问题
1. 完善PickManyByDotNotation泛型类型
你的核心需求是将多个点语法路径转换为对应的嵌套对象结构,需要通过路径转对象+对象合并的思路实现,而非递归处理数组元素。以下是完整的类型定义:
辅助类型:路径转嵌套对象
先实现将单个点路径转换为对应嵌套对象的类型:
type PathToObject<T, P extends string> = P extends `${infer K extends keyof T & string}.${infer R}` ? { [key in K]: PathToObject<T[K], R> } : P extends keyof T ? { [key in P]: T[P] } : never;
辅助类型:合并多个嵌套对象
实现递归合并多个对象类型,处理嵌套层级的合并:
type Merge<T extends object[]> = T extends [infer A extends object, ...infer B extends object[]] ? { [K in keyof A | keyof B]: K extends keyof A ? A[K] : K extends keyof B ? B[K] : never } extends infer M ? { [K in keyof M]: M[K] extends object ? Merge<[A[K] extends object ? A[K] : never, B[K] extends object ? B[K] : never]> : M[K] } : never : T extends [infer A extends object] ? A : {};
最终PickManyByDotNotation类型
结合上述两个辅助类型,遍历所有路径并合并结果:
// 保留你已实现的PickByDotNotation(可直接复用) type PickByDotNotation<TObject, TPath extends string> = TPath extends `${infer TKey extends keyof TObject & string}.${infer TRest}` ? PickByDotNotation<TObject[TKey], TRest> : TPath extends keyof TObject ? TObject[TPath] : never; // 完善后的PickManyByDotNotation type PickManyByDotNotation<T, P extends string[]> = Merge<{ [K in keyof P]: PathToObject<T, P[K] & string> }>;
测试验证
用你的示例测试,结果完全符合预期:
interface Test { customer: { email: string; name: string; phone: string; id: string }; }; type PickMany = PickManyByDotNotation<Test, ['customer.email', 'customer.name']>; // 类型结果:{ customer: { email: string; name: string } }
2. 为JavaScript函数添加TypeScript类型标注
假设你的函数名为pickManyByDot,以下是带完整类型标注的实现:
function pickManyByDot<T extends object, P extends string[]>( obj: T, paths: P ): PickManyByDotNotation<T, P> { const result = {} as PickManyByDotNotation<T, P>; paths.forEach(path => { const keys = path.split('.'); let source = obj; let target = result as any; for (let i = 0; i < keys.length; i++) { const key = keys[i]; // 初始化嵌套对象(非最后一层) if (i < keys.length - 1 && !target[key]) { target[key] = {}; } // 赋值(最后一层)或进入下一层 target[key] = i === keys.length - 1 ? source[key] : target[key]; source = source[key as keyof typeof source]; target = target[key]; } }); return result; }
使用示例
const testData: Test = { customer: { email: 'user@example.com', name: 'John Doe', phone: '123456789', id: '1001' } }; const pickedData = pickManyByDot(testData, ['customer.email', 'customer.name']); // pickedData类型:{ customer: { email: string; name: string } } // 运行时值:{ customer: { email: 'user@example.com', name: 'John Doe' } }
内容的提问来源于stack exchange,提问作者robquinn
相关产品推荐
相关产品推荐

