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

使用reduce向空对象添加键时的TypeScript类型问题

TypeScript:修复不可变对象处理函数中的隐式any类型错误

问题场景

编写了不可变对象处理函数reduceObjectImmutable,使用reduce将筛选后的键值对赋值给累加器acc时,acc[key]与object[key]均触发类型错误,提示因string类型无法索引空对象导致隐式any类型,要求不使用any解决该问题。

报错信息:

acc[key]
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.

object[key]
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
No index signature with a parameter of type 'string' was found on type '{}'

原代码:

// Reduce Object Immutable !! V2 dont use the delete operator which is slow.
export const reduceObjectImmutable = <T extends object>(
  arr: string[],
  obj: T
) => {
  // make a shallow copy
  const object = { ...obj };
  // get all object keys
  const keys = Object.keys(object);
  // filter keys that are not in the remove array
  const filteredKeys = keys.filter((key) => !arr.includes(key));
  // create new object with filtered keys
  const newObject = filteredKeys.reduce((acc, key) => {
    // Error on both...
    acc[key] = object[key];
    return acc;
  }, {});
  return newObject;
};

问题原因

  1. Object.keys()返回的类型是string[],而非keyof T,导致key被推断为string类型,无法直接用来索引类型为T的object和初始值为{}的acc。
  2. 累加器acc的初始值{}类型为{},TypeScript不允许用string类型的键去索引该类型,因此触发隐式any错误。

解决方案

方案一:修正reduce中的类型断言与泛型

通过类型断言明确键的类型,并指定累加器的正确类型,避免隐式any:

// Reduce Object Immutable !! V2 dont use the delete operator which is slow.
export const reduceObjectImmutable = <T extends object>(
  arr: string[],
  obj: T
) => {
  const object = { ...obj };
  // 将Object.keys结果断言为T的键数组
  const keys = Object.keys(object) as Array<keyof T>;
  // 过滤掉需要移除的键,将key转为string匹配arr的类型
  const filteredKeys = keys.filter((key) => !arr.includes(key as string));

  // 指定累加器类型为T的子集,避免索引错误
  const newObject = filteredKeys.reduce((acc, key) => {
    acc[key] = object[key];
    return acc;
  }, {} as Pick<T, keyof T>);

  // 返回更精确的类型:排除arr中存在的键后的T子集
  return newObject as Pick<T, Exclude<keyof T, typeof arr[number]>>;
};

方案二:使用Object.fromEntries简化实现

用Object.entries和Object.fromEntries替代reduce,代码更简洁且类型推断更友好:

export const reduceObjectImmutable = <T extends object>(
  arr: string[],
  obj: T
) => {
  return Object.fromEntries(
    Object.entries(obj).filter(([key]) => !arr.includes(key))
  ) as Pick<T, Exclude<keyof T, typeof arr[number]>>;
};

关键说明

  • 两种方案都未使用any,而是通过类型断言和精确泛型定义让TypeScript正确识别对象的键类型。
  • 返回类型使用Pick<T, Exclude<keyof T, typeof arr[number]>>,明确表示返回的是原对象排除指定键后的子集,比泛泛的object类型更具类型安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:45:34