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

TypeScript严格模式下reduce分组函数报错:Type 'undefined'不可用作索引类型

解决TypeScript严格模式下groupBy函数的"Type 'undefined' cannot be used as an index type"错误

问题场景

你需要实现一个函数,将对象数组按指定key的值分组,例如输入:

const input = [{name: 'name-1', foo: 'bar'}, {name: 'name-2', foo: 'bar'}];

期望输出:

{ 'bar': [{name: 'name-1', foo: 'bar'}, {name: 'name-2', foo: 'bar'}] }

但使用reduce实现时,TypeScript严格模式下触发错误:Type 'undefined' cannot be used as an index type。

错误代码示例

通常出错的代码类似这样:

function groupBy<T>(array: T[], key: keyof T) {
  return array.reduce((acc, item) => {
    const groupKey = item[key];
    // 此处触发索引类型错误
    acc[groupKey] = acc[groupKey] || [];
    acc[groupKey].push(item);
    return acc;
  }, {} as Record<string, T[]>);
}

错误原因

TypeScript严格模式下,keyof T对应的属性值可能包含undefined(比如T中该属性是可选类型,或属性值类型允许undefined),而对象的索引类型只能是string、number或symbol,因此直接用可能为undefined的groupKey作为索引会触发错误。

解决方案

方案1:约束分组键为合法索引类型

通过泛型约束,确保指定key对应的属性值必须是string/number/symbol类型,从根源避免undefined作为索引:

function groupBy<T, K extends keyof T>(
  array: T[],
  key: K
): Record<T[K] extends string | number | symbol ? T[K] : never, T[]> {
  return array.reduce((acc, item) => {
    const groupKey = item[key] as T[K] & (string | number | symbol);
    acc[groupKey] = acc[groupKey] || [];
    acc[groupKey].push(item);
    return acc;
  }, {} as Record<T[K] extends string | number | symbol ? T[K] : never, T[]>);
}

方案2:处理undefined分组键

如果业务需要保留属性值为undefined的项,可将undefined转换为合法的索引值(比如字符串'undefined'):

function groupBy<T>(array: T[], key: keyof T) {
  return array.reduce((acc, item) => {
    const groupKey = item[key];
    // 将undefined转为字符串键,确保索引合法
    const safeKey = groupKey === undefined ? 'undefined' : (groupKey as string | number | symbol);
    acc[safeKey] = acc[safeKey] || [];
    acc[safeKey].push(item);
    return acc;
  }, {} as Record<string | number | symbol, T[]>);
}

方案3:过滤属性值为undefined的项

如果业务不需要将属性值为undefined的项纳入分组,直接过滤这些元素即可:

function groupBy<T>(array: T[], key: keyof T) {
  return array.reduce((acc, item) => {
    const groupKey = item[key];
    // 仅处理属性值不为undefined的项
    if (groupKey !== undefined) {
      const safeKey = groupKey as string | number | symbol;
      acc[safeKey] = acc[safeKey] || [];
      acc[safeKey].push(item);
    }
    return acc;
  }, {} as Record<string | number | symbol, T[]>);
}

测试示例

使用任意一种方案测试:

const input = [{name: 'name-1', foo: 'bar'}, {name: 'name-2', foo: 'bar'}];
const result = groupBy(input, 'foo');
console.log(result);
// 输出:{ bar: [ { name: 'name-1', foo: 'bar' }, { name: 'name-2', foo: 'bar' } ] }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:57:34