如何在TypeScript中实现groupBy函数动态排除指定键的类型?
TypeScript groupBy函数类型优化:实现按指定键分组后排除该键的类型
问题场景
你编写了一个groupBy函数,期望调用时能根据传入的分组键,自动推导出去除该键后的类型:
原函数代码:
const groupBy = <T extends Record<keyof T, unknown>>(arr: T[], key: keyof T) => { return arr.reduce((prev, { [key]: k, ...rest }) => { if (!prev[k]) prev[k] = [] as Omit<T, keyof T>[]; prev[k].push(rest); return prev; }, {} as Record<keyof T, Omit<T, keyof T>[]>); };
定义的类型和数组:
type MyType = { city: number, name: string } const L: MyType[] = [ { city: 1, name: "name1" }, { city: 1, name: "name2" }, { city: 2, name: "name3" }, { city: 2, name: "name4" } ]
期望调用const grouped = groupBy(L, "city")时,grouped的类型为Record<number, Omit<MyType, "city">[]>——即分组键对应的值类型作为Record的键,数组项自动排除该分组键。
解决方案
完全可行,只需调整泛型定义,把分组键作为独立的泛型参数,让TypeScript精准推导类型:
修改后的groupBy函数:
const groupBy = <T extends Record<string, unknown>, K extends keyof T>(arr: T[], key: K) => { return arr.reduce((prev, { [key]: k, ...rest }) => { if (!prev[k]) { prev[k] = [] as Omit<T, K>[]; } prev[k].push(rest); return prev; }, {} as Record<T[K], Omit<T, K>[]>); };
关键调整说明
- 新增泛型参数
K extends keyof T:捕获具体的分组键类型(比如调用时的"city"),而非宽泛的keyof T联合类型。 - 返回值类型改为
Record<T[K], Omit<T, K>[]>:T[K]对应分组键值的类型(比如MyType["city"]就是number);Omit<T, K>是从T中排除指定键K后的类型(比如Omit<MyType, "city">即{ name: string })。
- 修正reduce初始值的类型断言,与返回值类型保持一致。
现在调用groupBy(L, "city")时,grouped的类型会自动推导为Record<number, { name: string }[]>,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Elyasaf755
相关产品推荐
相关产品推荐

