You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>;
}

关键细节说明

  1. 递归类型DeepValue:
    拆解键数组,逐层匹配对象的键:如果当前键存在,就继续递归处理剩余键和对应值;如果键不存在,直接返回undefined;没有剩余键时返回当前值的类型,同时保留undefined的可能性(毕竟存在键找不到的情况)。

  2. 函数参数的类型约束:

    • keys: [...K]用元组展开写法,能让TypeScript记住键数组每个元素的具体类型,而非笼统的string[],这样才能精准推导返回值。
    • obj: T用泛型T约束为任意对象类型,适配不同结构的输入对象。
  3. 类型断言:
    由于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:57:15