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

TypeScript泛型报错:groupBy函数类型问题及修复咨询

修复TypeScript中groupBy函数的类型错误

原始代码与错误

你编写的groupBy函数及调用代码如下:

export const groupBy = <T, K extends string>(array: T[], key: K): Record<K, T> => {
  return array.reduce((acc, item) => {
    if (!acc[key]) {
      acc[key] = []
    }
    acc[key].push(item)
    return acc
  }, {} as Record<K, T[]>)
}

const arr = [{name: "Car"}, {name: 'Color'}, {name: "Car"}]

interface Data {
  name: string
}

const res = groupBy<Data[], 'Car' | 'Color'>(arr, 'name')
console.log(res)

调用时出现的TypeScript错误:

Argument of type '{ name: string; }[]' is not assignable to parameter of type 'Data[][]'.
  Type '{ name: string; }' is missing the following properties from type 'Data[]': length, pop, push, concat, and 26 more.(2345)
const arr: {
    name: string;
}[]

问题根源

  1. 泛型参数传递错误:你将第一个泛型参数指定为Data[],但函数定义中第一个泛型T是数组元素的类型,而非数组本身,导致TypeScript期望传入Data[][]类型的参数,与实际的Data[]不匹配。
  2. 函数返回类型定义错误:返回类型标注为Record<K, T>,但实际返回的是Record<K, T[]>(每个键对应一个元素数组),类型不匹配。
  3. 键类型的约束不合理:K extends string没有关联到元素类型T的键,无法保证key是T上存在的属性。

修复方案

调整泛型定义、参数类型和返回类型,让TypeScript能正确推断类型并提供代码提示:

修复后的完整代码

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

const arr = [{name: "Car"}, {name: 'Color'}, {name: "Car"}];

interface Data {
  name: string;
}

// 无需手动指定泛型,TypeScript会自动推断
const res = groupBy(arr, 'name');
// 或手动指定泛型(可选)
// const res = groupBy<Data, 'name'>(arr, 'name');

console.log(res);
// 此时res的类型为Record<'Car' | 'Color', Data[]>,能获得完整代码提示

关键修复点说明

  • 泛型约束关联:将K extends string改为K extends keyof T,确保key参数是元素类型T上存在的属性,避免传入无效键。
  • 返回类型精准化:使用Extract<T[K], string | number | symbol>提取T[K]中可作为对象键的类型(string/number/symbol),让返回值的键类型是该属性的实际取值联合类型(比如示例中的'Car' | 'Color')。
  • 修正泛型传递:调用时无需手动指定键的联合类型,TypeScript会自动从数组元素的属性值中推断出结果的键类型;若手动指定泛型,只需传入元素类型Data和属性名'name'即可。

效果验证

修复后:

  1. 能指定数组元素的类型(通过泛型T或自动推断);
  2. 结果的键类型自动推断为属性值的联合类型;
  3. 使用res时,TypeScript会提供'Car'和'Color'的代码提示,且每个键对应的数组元素类型为Data。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:00:03