The groupBy function is generally used to group arrays together by a certain condition. You can easily go for a built-in solution, such as lodash’s groupBy function, or implement it yourself in TypeScript.

Lodash _.groupBy

Lodash is a library that contains a large selection of utility functions, such as for flattening arrays, sorting arrays, debouncing functions, etc.

To set up Lodash with TypeScript, you’ll need to install the types with:

npm install --save-dev @types/lodash
_.groupBy(collection, [iteratee=_.identity])

The Lodash groupby function takes an array, and either a function, or a property to group them by. It will then return an object with the grouped values, e.g.

const people = ['Adam', 'Brian', 'Carl', 'Dan', 'Edd'];
console.log(_.groupBy(people, 'length'));

groupBy

Here’s my implementation of the same function:

function groupBy<T>(arr: T[], fn: (item: T) => any) {
    return arr.reduce<Record<string, T[]>>((prev, curr) => {
        const groupKey = fn(curr);
        const group = prev[groupKey] || [];
        group.push(curr);
        return { ...prev, [groupKey]: group };
    }, {});
}

Let’s break this down step by step:

  • Our function is generic, depending on the type of the items in our array
  • The first parameter is our array, and the second parameter is any function that takes an item in our array and gives us anything back
  • We use reduce to process through our array, and get out a new type
  • Giving reduce a type here helps TypeScript understand what we want out from our reduce; in this case an object with anything as keys, and arrays of our items as values

Then inside the Reduce:

  • We get which group the item should be in by putting it through our function
  • Then we get the array, or if the array doesn’t exist, just a blank array
  • Then we add our new item to the group array
  • Then we update the object with the new value, and return it for the next iteration of reduce

Let’s have a go at using our new function:

Converting the Lodash groupBy to our function is simple. Instead of providing a property to group by we provide a function that returns the property:

console.log(groupBy(people, (p) => p.length));

Here’s a little more complex example, using our groupBy function to group users together in age categories:

const people = [
    { name: 'Adam', age: 21 },
    { name: 'Brian', age: 10 },
    { name: 'Carla', age: 19 },
    { name: 'Daniel', age: 14 },
    { name: 'Ellie', age: 42 },
];

const result = groupBy(people, (e) => {
    if (e.age < 13) return 'child';
    if (e.age < 20) return 'teenager';
    return 'adult';
});

We can categorise our list of people with a simple if statement, and return the correct group for their age.

Built-In

There’s an experimental proposal for a .group() method. Browser support for it is very scarce, and you can check that out here. This function will work exactly the same as my implementation, with the only difference being it will be a method on the array. This means you’ll call it using array.group(), instead of groupBy(array).

The previous example would look a little something like:

const people = [
    { name: 'Adam', age: 21 },
    { name: 'Brian', age: 10 },
    { name: 'Carla', age: 19 },
    { name: 'Daniel', age: 14 },
    { name: 'Ellie', age: 42 },
];

const result = people.group(p) => {
    if (e.age < 13) return 'child';
    if (e.age < 20) return 'teenager';
    return 'adult';
})

Since support for this function is so low, I’d stick to one of the first two methods for now, but this could be something to keep an eye on!

Conclusion

Thanks for reading this article on how to implement groupBy in TypeScript. Hopefully, you found this article useful, either because you’ve found the code you’re looking for, or hopefully I gave a useful explanation of how it works underneath.

If I did help you out, if you’re having any more issues, or if you simply liked the article, feel free to leave a comment below!

Avatar photo
👋 Hey, I'm Omari Thompson-Edwards
Hey, I'm Omari! I'm a full-stack developer from the UK, with a passion for ReactJS. I'm an enthusiastic and hardworking junior developer, driven by a desire to learn and explore ideas.

💬 Leave a comment

Your email address will not be published.

We will never share your email with anyone else.