我想写一个groupBy
功能,到目前为止,类型系统对我的工作不太满意。
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[] }
我得到的第一个错误是 R
在{ [group: R]: T[] }
不是 string
或 number
.
签名实际上对数据集根本不起作用
group([{ name: 'Johnny Appleseed', age: 17 }], 'name') // R should be string
group([{ name: 'Johnny Appleseed', age: 17 }], 'age') // R should be never
但是,R
是never
同时 K
是"name" | "age"
我必须使用 group<{name: string, age: number}, 'name'>
手动缩小类型参数范围制作R
是string
.
最佳答案
索引签名必须是string
或number
。没有联合类型,没有泛型类型,除了 string
或 number
之外什么都做不了。
如果您使用两个函数签名,我们仍然可以实现您想要的行为,一个只接受 string
键,另一个只接受 number
键:
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` 打字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52492978/