如何为函数参数生成TypeScript嵌套键类型与动态返回类型?
实现嵌套键路径的动态类型返回函数
完整代码实现
// 生成所有嵌套键路径(点分隔形式) type NestedKey<S> = S extends object ? { [K in keyof S & string]: K | `${K}.${NestedKey<S[K]>}`; }[keyof S & string] : never; // 根据键路径获取对应嵌套类型 type PathValue<S, K extends NestedKey<S>> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof S ? PathValue<S[Key], Rest & NestedKey<S[Key]>> : never : K extends keyof S ? S[K] : never; // 定义返回的函数类型(重载形式) type ReturnFn<S> = { (): S; <K extends NestedKey<S>>(target: K): PathValue<S, K>; }; // 实现test函数 function test<S>(data: S): ReturnFn<S> { return ((target?: string) => { let result: any = data; target?.split(".").forEach(k => result = result[k]); return result; }) as ReturnFn<S>; } // 测试示例 const data = { suggestion: {a: {nested: true}} }; const result = test(data); const fullData = result(); // 类型为 { suggestion: { a: { nested: boolean; }; }; } const suggestion = result("suggestion"); // 类型为 { a: { nested: boolean; }; } const suggestionA = result("suggestion.a"); // 类型为 { nested: boolean; } const nestedValue = result("suggestion.a.nested"); // 类型为 boolean
关键类型解析
NestedKey
递归遍历对象的所有层级,生成所有可能的点分隔键路径联合类型。比如示例中会生成"suggestion"、"suggestion.a"、"suggestion.a.nested"这些字符串字面量。核心逻辑是:
- 仅处理对象类型的输入;
- 对每个字符串类型的键,拼接当前键与子对象的嵌套路径,递归生成完整路径;
- 通过索引访问将所有路径合并为联合类型。
PathValue<S, K>
根据传入的键路径K,从对象S中提取对应位置的类型。核心逻辑是:
- 用模板字符串类型拆分路径为当前键和剩余路径;
- 递归处理剩余路径,直到遍历完整个路径,返回最终的类型。
ReturnFn
采用函数重载定义两种调用场景:
- 无参数调用时,返回原对象类型S;
- 传入合法嵌套键路径时,返回对应位置的类型。
函数实现说明
函数内部逻辑与你提供的JavaScript逻辑一致,通过可选链和forEach遍历路径节点,最终返回对应的值。使用类型断言将返回值指定为ReturnFn<S>,让TypeScript正确识别函数的重载类型。
内容的提问来源于stack exchange,提问作者Arnaud
相关产品推荐
相关产品推荐

