TypeScript如何为该递归函数正确添加类型(参数+返回值)?
给deepValue函数加TypeScript类型标注的正确姿势
这个函数是靠字符串键数组递归获取对象深层值的,要让TypeScript能准确识别返回值类型,得用递归泛型跟踪每一层的键和对应值的类型,具体写法如下:
完整带类型的代码
// 定义递归类型,推导最终返回值的类型 type DeepValue<T, K extends string[]> = K extends [infer First, ...infer Rest] ? First extends keyof T ? Rest extends string[] ? T[First] extends Record<string, any> ? DeepValue<T[First], Rest> : T[First] | undefined : T[First] | undefined : undefined : T | undefined; function deepValue<T extends Record<string, any>, K extends string[]>( keys: [...K], // 用元组展开保留键数组的具体元素类型 obj: T ): DeepValue<T, K> { const key = keys.shift(); if (key === undefined || !(key in obj)) return undefined as DeepValue<T, K>; const value = obj[key]; // 补充value !== null判断,排除null的干扰(null的typeof也是object) if (keys.length > 0 && typeof value === 'object' && value !== null) { return deepValue(keys, value) as DeepValue<T, K>; } return value as DeepValue<T, K>; }
关键细节说明
递归类型DeepValue:
拆解键数组,逐层匹配对象的键:如果当前键存在,就继续递归处理剩余键和对应值;如果键不存在,直接返回undefined;没有剩余键时返回当前值的类型,同时保留undefined的可能性(毕竟存在键找不到的情况)。函数参数的类型约束:
keys: [...K]用元组展开写法,能让TypeScript记住键数组每个元素的具体类型,而非笼统的string[],这样才能精准推导返回值。obj: T用泛型T约束为任意对象类型,适配不同结构的输入对象。
类型断言:
由于TypeScript对递归类型的推导存在局限,所以用as DeepValue<T, K>让编译器通过检查,不影响实际类型推导的准确性。
修正后的使用示例
原示例中'animals.mammals.apes.count'.split('.')得到的键数组第一个元素是animals,但animals对象本身没有这个键,因此调整为正确的键数组:
const animals = { mammals: { apes: { count: 5 } } }; const keys = 'mammals.apes.count'.split('.'); const count = deepValue(keys, animals); // TypeScript会自动识别count的类型为number | undefined
内容的提问来源于stack exchange,提问作者PenthousePauper
相关产品推荐
相关产品推荐

