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

TypeScript:正确定义GroupBy泛型函数类型遇到困难

解决TypeScript GroupBy泛型函数的类型错误问题

问题根源

原函数的泛型设计不够精准:

  • 仅用T作为泛型参数,key: keyof T会让TypeScript将分组键值视为所有T属性值的联合类型,而非指定键对应的具体值类型,导致索引类型不匹配
  • Partial<Record<...>>使得TypeScript无法确定acc[group]一定存在,触发"Object is possibly 'undefined'"警告

修正方案

引入第二个泛型参数K extends keyof T,明确指定分组的目标键,让类型系统精准识别分组键值的类型,同时通过赋值操作确保acc[group]的存在性:

function groupBy<T, K extends keyof T>(data: T[], key: K): Partial<Record<T[K], T[]>> {
  return data.reduce((acc, item) => {
    const group = item[key];
    // 确保当前分组存在,不存在则初始化空数组
    acc[group] = acc[group] ?? [];
    // 此时acc[group]已被确认为非undefined,可安全push
    acc[group].push(item);
    return acc;
  }, {} as Partial<Record<T[K], T[]>>);
}

type Human = {
  gender: 'female' | 'male' | 'prefer not to say';
  name: string;
  age: number;
};

const data: Human[] = [
    { name: 'John', age: 20, gender: 'male' },
    { name: 'Jane', age: 20, gender: 'female' },
    { name: 'Jack', age: 30, gender: 'male' },
    { name: 'Jane', age: 50, gender: 'female' },
];

const groupedByGenders = groupBy(data, 'gender');
// 类型自动推导为:Partial<Record<'female' | 'male' | 'prefer not to say', Human[]>>

console.log(groupedByGenders.female); // 自动补全,类型为Human[] | undefined
console.log(groupedByGenders.male); // 自动补全,类型为Human[] | undefined
console.log(groupedByGenders['prefer not to say']); // 自动补全,类型为undefined

关键修改说明

  1. 泛型参数优化:K extends keyof T让TypeScript锁定分组键为T的某个具体属性,而非所有属性的联合,确保返回类型的键是该属性的具体值类型(比如Human['gender']的字面量联合)
  2. 类型安全保障:通过acc[group] = acc[group] ?? []的赋值操作,TypeScript能推断出后续acc[group]一定是T[]类型,消除"Object is possibly 'undefined'"警告
  3. 自动补全支持:返回类型Partial<Record<T[K], T[]>>让TypeScript能自动补全所有可能的分组键,并识别未出现的键值为undefined

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 08:04:45