TypeScript `groupBy` typings

こ雲淡風輕ζ 提交于 2021-02-05 07:10:50

问题


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[] }

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

However, both R is never while K is "name" | "age"

I have to manually narrow down type parameter with group<{name: string, age: number}, 'name'> to make R be string.


回答1:


An index signature must be either string or number. No union types, no generic types nothing else will do except string or 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')


来源:https://stackoverflow.com/questions/52492978/typescript-groupby-typings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!