TypeScript递归映射对象属性类型:实现层级属性路径生成函数
实现类型安全的嵌套路径构建器
嘿,这个类型安全的嵌套路径构建需求我太熟悉了!刚好可以用TypeScript的泛型和条件类型完美实现,每次调用都严格限制只能选当前层级对象的合法键,还能自动把路径累积起来。下面是我整理的可行方案,完全符合你的需求:
核心思路
我们需要一个路径构建器,它能:
- 追踪当前操作的对象类型,确保每次调用只能传入该类型的合法键
- 自动累积已选择的路径
- 最后通过
path属性返回完整的路径数组
利用TypeScript的泛型可以精准约束每一步的键类型,再通过闭包来保存路径的状态,就能实现这个功能。
完整代码实现
// 定义路径构建器的核心接口,泛型T是当前层级的对象类型,P是已累积的路径数组类型 interface PathBuilder<T, P extends string[]> { // 下一次调用时,只能传入当前类型T的键,同时更新路径和当前类型 <K extends keyof T>(key: K): PathBuilder<T[K], [...P, K & string]>; // 只读属性,返回完整的路径数组 readonly path: P; } // 重载path函数,支持两种调用方式:直接传初始键,或者先初始化再链式调用 function path<T>(initialKey: keyof T): PathBuilder<T[keyof T], [keyof T & string]>; function path<T>(): PathBuilder<T, []>; function path<T>(initialKey?: keyof T): any { // 用闭包保存当前路径 const currentPath: string[] = initialKey ? [initialKey as string] : []; // 构建器函数,每次调用添加新键并返回自身 const builder = <K extends keyof any>(key: K): any => { currentPath.push(key as string); return builder; }; // 给构建器添加只读的path属性,返回路径副本避免外部修改 Object.defineProperty(builder, 'path', { get: () => [...currentPath], enumerable: true }); return initialKey ? builder : builder; }
使用示例与类型验证
先把你的接口定义放进来:
interface Model { bla: Child1; bwap: string; } interface Child1 { blu: Child2[]; } interface Child2 { whi: string; }
按照你的需求调用:
let mapper = path<Model>("bla")("blu"); let myPropertyPath = mapper.path; // 类型为["bla", "blu"],实际值也是这个数组
类型安全验证
TypeScript会自动检查每一步的键是否合法:
- 如果尝试传入
Model不存在的键,比如path<Model>("invalidKey"),会直接报错 - 如果在
"bla"之后传入Child1不存在的键,比如path<Model>("bla")("invalidKey"),同样会报错
甚至支持更深层级的嵌套,比如访问数组元素的属性:
let deepMapper = path<Model>("bla")("blu")("0")("whi"); console.log(deepMapper.path); // 输出 ["bla", "blu", "0", "whi"]
这个方案完全满足你的要求,而且类型约束非常严格,能在编译期就避免路径错误。
内容的提问来源于stack exchange,提问作者Timothy Degryse
相关产品推荐
相关产品推荐

