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
关键修改说明
- 泛型参数优化:
K extends keyof T让TypeScript锁定分组键为T的某个具体属性,而非所有属性的联合,确保返回类型的键是该属性的具体值类型(比如Human['gender']的字面量联合) - 类型安全保障:通过
acc[group] = acc[group] ?? []的赋值操作,TypeScript能推断出后续acc[group]一定是T[]类型,消除"Object is possibly 'undefined'"警告 - 自动补全支持:返回类型
Partial<Record<T[K], T[]>>让TypeScript能自动补全所有可能的分组键,并识别未出现的键值为undefined
内容的提问来源于stack exchange,提问作者Norfeldt
相关产品推荐
相关产品推荐

