问题描述
我想编写一个 groupBy
函数,到目前为止,类型系统对我的工作并不满意.
I want to write a groupBy
function, so far the type system is not so happy with my work.
export function group<
T extends object,
K extends (keyof T & string),
R = T[K] extends string ? string : never
>(
data: T[],
groupBy: keyof T
): { [group: R]: T[] }
我得到的第一个错误是 {[group:R]:T []}
中的 R
不是 string
或数字
.
The first error that I got is that R
in { [group: R]: T[] }
is not string
or number
.
对于的数据集,签名实际上根本不起作用
The signature actually doesn't work at all for the data set of
group([{ name: 'Johnny Appleseed', age: 17 }], 'name') // R should be string
group([{ name: 'Johnny Appleseed', age: 17 }], 'age') // R should be never
但是,两个 R
都是从不
,而 K
都是"name" |年龄"
However, both R
is never
while K
is "name" | "age"
我必须使用 group< {name:string,age:number},'name'>
来手动缩小类型参数,以使 R
为字符串
.
I have to manually narrow down type parameter with group<{name: string, age: number}, 'name'>
to make R
be string
.
推荐答案
索引签名必须为 string
或 number
.没有联合类型,没有泛型类型,除了 string
或 number
之外,别无其他.
An index signature must be either string
or number
. No union types, no generic types nothing else will do except string
or number
.
如果您使用两个函数签名,一个仅接受 string
键,而另一个仅接受 number
键,我们仍然可以实现您想要的行为:
We can still achieve the behavior you want if you use two function signatures, one that accepts only string
keys and the other that only accepts number
keys:
export declare function group<T extends Record<K, string>, K extends string>(data: T[], groupBy: K): { [group: number]: T[] }
export declare function group<T extends Record<K, number>, K extends string>(data: T[], groupBy: K): { [group: string]: T[] }
let groupByString = group([{ name: 'Johnny Appleseed', age: 17 }], 'name')
let groupByNumber = group([{ name: 'Johnny Appleseed', age: 17 }], 'age')
这篇关于TypeScript`groupBy`类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!