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

如何为数组键取嵌套对象值的reduce函数定义TypeScript类型?

问题描述

有如下嵌套对象:

// nested object
const obj = {
  one: {
    two: {
      three: 'xxxx',
    },
    four: {
      five: 5,
    },
    six: [1, 2, 3],
  },
}

希望通过键数组从该嵌套对象中获取对应值,以下JavaScript代码可正常运行,但在TypeScript中无法通过类型校验:

const result = ['one', 'two', 'four'].reduce(
  (acc, key) => acc[key],
  obj,
)
// undefined

const result = ['one', 'two', 'three'].reduce(
  (acc, key) => acc[key],
  obj,
)
// xxxx

const result = ['one', 'six'].reduce(
  (acc, key) => acc[key],
  obj,
)
//  [1, 2, 3]

TSLint报错信息:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ one: { two: { three: string; }; four: { five: number; }; six: number[]; }; }'. No index signature with a parameter of type 'string' was found on type '{ one: { two: { three: string; }; four: { five: number; }; six: number[]; }; }'.ts(7053)

已知报错原因是键数组中的元素被推断为string类型,无法匹配对象的具体键类型,需要可行的类型定义方案。


解决办法

1. 用递归泛型实现强类型路径校验(推荐)

可以写一套类型工具,让TypeScript能识别嵌套对象的合法路径,同时自动推导返回值类型:

// 定义对象的合法嵌套路径类型
type Path<T> = T extends object
  ? { [K in keyof T]: [K] | [K, ...Path<T[K]>] }[keyof T]
  : [];

// 实现取值函数
function getNestedValue<T, P extends Path<T>>(obj: T, path: P): P extends [infer K, ...infer Rest]
  ? Rest extends Path<T[K]>
    ? getNestedValue<T[K], Rest>
    : T[K]
  : T {
  return path.reduce((acc, key) => acc[key], obj) as any;
}

// 使用示例
const result1 = getNestedValue(obj, ['one', 'two', 'four']); // 类型自动推断为 undefined
const result2 = getNestedValue(obj, ['one', 'two', 'three']); // 类型自动推断为 string
const result3 = getNestedValue(obj, ['one', 'six']); // 类型自动推断为 number[]

这个方案会在编译阶段就拦截无效路径,同时保留完整的类型信息,最符合TypeScript的类型安全理念。

2. 简易类型断言快速消错

如果不需要严格的类型校验,只是想先消除报错,可以给acc加个类型断言:

const result = ['one', 'two', 'three'].reduce(
  (acc, key) => (acc as Record<string, any>)[key],
  obj,
);

缺点是返回值会变成any,丢失类型推导,适合临时快速解决问题的场景。

3. 类型守卫做基础类型检查

想要兼顾一点类型安全又不想写复杂工具,可以用类型守卫缩小acc的类型范围:

const result = ['one', 'two', 'three'].reduce((acc, key) => {
  if (typeof acc === 'object' && acc !== null && key in acc) {
    return acc[key as keyof typeof acc];
  }
  return undefined;
}, obj);

这种方式下返回值会被推断为string | undefined,能避免完全的any,同时做基础的合法性检查。


内容的提问来源于stack exchange,提问作者Yutaka Fujii

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:07:29