TypeScript递归函数类型定义:解决value类型any与编译报错
解决TypeScript递归查找嵌套对象键值的类型定义问题
你写的这个递归函数用来遍历嵌套或非嵌套对象、提取指定键的值,但目前存在两个问题:递归调用时曾出现重载不匹配(靠给reduce指定泛型<T[]>临时解决了),但value参数始终是any类型,触发lint告警。下面是完善后的类型定义方案:
原问题代码
const findName = <T extends object>(obj: T, keyToFind: string): T[] => { return Object.entries(obj) .reduce<T[]>((acc, [key, value]) => { if(key === keyToFind) { return acc.concat(value) } else { // 判断是否是嵌套对象,继续递归查找 if (typeof value === 'object') { return acc.concat(findName(value, keyToFind)) } else { return acc } } }, []) }
解决方案1:基础类型约束(消除any)
先定义一个递归类型NestedObject,明确表示可以嵌套的对象结构,避免any:
// 定义递归嵌套对象类型:值可以是unknown或另一个嵌套对象 type NestedObject = { [key: string]: unknown | NestedObject; }; const findName = (obj: NestedObject, keyToFind: string): unknown[] => { return Object.entries(obj).reduce<unknown[]>((acc, [key, value]) => { if (key === keyToFind) { return acc.concat(value); } else { // 排除null(typeof null会返回'object',但null不是对象) if (typeof value === 'object' && value !== null) { return acc.concat(findName(value as NestedObject, keyToFind)); } else { return acc; } } }, []); };
解决方案2:泛型优化(精确返回类型)
如果提前知道目标键对应的值类型,可以用泛型让返回类型更精准:
// 带泛型的递归嵌套对象类型,指定值的类型 type NestedObject<T = unknown> = { [key: string]: T | NestedObject<T>; }; const findName = <T>(obj: NestedObject<T>, keyToFind: string): T[] => { return Object.entries(obj).reduce<T[]>((acc, [key, value]) => { if (key === keyToFind) { return acc.concat(value as T); } else { if (typeof value === 'object' && value !== null) { return acc.concat(findName(value as NestedObject<T>, keyToFind)); } else { return acc; } } }, []); };
关键改进点
- 用
NestedObject递归类型替代原有的T extends object,明确对象的嵌套结构,彻底消除any类型。 - 增加
value !== null的判断,避免把null误判为对象进行递归调用。 - 泛型版本可以根据实际场景指定值类型,让函数返回类型更准确。
内容的提问来源于stack exchange,提问作者Jorge Guerreiro
相关产品推荐
相关产品推荐

