i made a type-safe GroupBy function.
/**
* Groups array of objects by a given key
* @param arr array of objects to group
* @param key must be present on every object, and it's values must be string|number
* @author telepresence
* @license CC-BY-4.0
*/
function groupBy(arr: T[], key: keyof T, defaultAcc: Record = {}) {
return arr.reduce((acc, val, i) => {
const compValue = val[key];
if (typeof compValue !== 'string' && typeof compValue !== 'number') {
throw new Error(`key ${key.toString()} has values other than string/number. can only group by string/number values`);
}
if (!acc[compValue]) acc[compValue] = []
acc[compValue].push(val);
return acc;
}, defaultAcc);
}
- like lodash's groupBy, but by key and not function
- group an array of objects which all have a key in common into an object with keys matching all the different possible values of your common key
- type-safe, no unknown's no any's
- does not copy arrays ([...array]), uses push
- supports selecting by keys, where the key values are string / number (although you can easily add symbol support)
- shared for free under the CC BY 4.0 license - only attribution is requred (link to this post is fine)
- custom default accumulator support, if you already know the groups beforehand and would rather have an empty array than undefined.
example:
const data = [{
"name": "jim",
"color": "blue",
"age": "22"
}, {
"name": "Sam",
"color": "blue",
"age": "33"
}, {
"name": "eddie",
"color": "green",
"age": "77"
}];
groupBy(data, 'color')
would result into:
{
"blue": [
{
"name": "jim",
"color": "blue",
"age": "22"
},
{
"name": "Sam",
"color": "blue",
"age": "33"
}
],
"green": [
{
"name": "eddie",
"color": "green",
"age": "77"
}
]
}
TL;DR i've sucessfully wrote something using generics in typescript for the first time, and i think it's pretty epic.