Reputation: 5625
Let's say we have the following array of objects and we want to group them by property (here color)
Here is how I wrote it in JS
const users = [
{ name: 'Jim', color: 'blue' },
{ name: 'Sam', color: 'blue' },
{ name: 'Eddie', color: 'green' },
]
function groupBy(array, property) {
return array.reduce((accu, curr) => {
const value = curr[property]
if (accu[value]) {
accu[value].push(curr)
} else {
accu[value] = [curr]
}
return accu
}, {})
}
const usersByColor = groupBy(users, 'color') // TODO: implement groupBy
And I am trying to write it in TypeScript
type GroupedArray<T, K extends keyof T> = {
[P in T[K]]: T[] // 🚨here it errors on `Type 'T[K]' is not assignable to type 'string | number | symbol'.`
}
function groupBy<T, K extends keyof T>(array: T[], prop: K) {
return array.reduce((accu, curr) => {
const value = curr[prop]
if (accu[value]) {
accu[value].push(curr)
} else {
accu[value] = [curr]
}
return accu
}, {} as GroupedArray<T, K>)
}
const users = [
{ name: 'Jim', color: 'blue' },
{ name: 'Sam', color: 'blue' },
{ name: 'Eddie', color: 'green' },
]
const usersByColor = groupBy(users, 'color')
I got an type error for on
type GroupedArray<T, K extends keyof T> = {
[P in T[K]]: T[]
}
for Type 'T[K]' is not assignable to type 'string | number | symbol'.
I wonder what is the right way to type it?
or is there a better way to write such a function in TypeScript
Upvotes: 1
Views: 326
Reputation: 71
you should give your params a limit type
type GroupedArray<T extends Record<K, PropertyKey>, K extends keyof T> = {
[P in T[K]]: T[]
}
function groupBy<T extends Record<K, PropertyKey>, K extends keyof T>(array: T[], prop: K) {
return array.reduce((accu, curr) => {
const value = curr[prop]
if (accu[value]) {
accu[value].push(curr)
} else {
accu[value] = [curr]
}
return accu
}, {} as GroupedArray<T, K>)
}
const users = [
{ name: 'Jim', color: 'blue' },
{ name: 'Sam', color: 'blue' },
{ name: 'Eddie', color: 'green' },
]
const usersByColor = groupBy(users, 'color')
Upvotes: 2
Reputation: 35512
Force the values of T
to be string | number | symbol
:
type GroupedArray<T extends Record<any, string | number | symbol>, K extends keyof T> = {
[P in T[K]]: T[]
}
Upvotes: 0