Category Archives: TypeScript

8 Examples of Using Reduce in TypeScript

This post shows common use cases for reduce in TypeScript. The examples include how to imitate SQL’s aggregate functions, such as count and sum.

All examples use the same array of blog posts, and each example is self-contained and can be easily copy/pasted (into TypeScript’s Playground.)

Happy coding!

Examples 1: Find the min element in an array using reduce

When we have an array of objects, reduce is an easy way to identify the smallest element. For example, if we want to find the blog post with the least number of likes, we can do it like this:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const worstPost = posts.reduce((worstPost, post) => worstPost.likes < post.likes ? worstPost : post);

console.log(worstPost.title); // Output: "Stateless React"

Example 2: Find the max element in an array using reduce

When we have an array of objects, reduce is an easy way to identify the largest element. For example, if we want to find the blog post with the most likes, we can do it like this:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const bestPost = posts.reduce((bestPost, post) => bestPost.likes > post.likes ? bestPost : post);

console.log(bestPost.title); // Output: "Clean TypeScript"

Example 3: Make an array unique using reduce

If we have a non-unique array of objects, we can use reduce to make it unique. For example, if we want to see a unique list of categories used in a number of blog posts, we can do it like this:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const uniqueCategories = posts
    .map(post => post.category)
    .reduce((categories, c) => categories.includes(c) ? categories : [...categories, c], new Array<string>());

console.log(uniqueCategories); // Output: ["TypeScript", "React"]

The behavior is similar to SELECT DISTINCT category FROM Posts in SQL.

In fairness, using a Set (and not reduce) is a better choice in this use case where we are using an array of values (and not objects):

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const categories = [ ...new Set(posts.map(post => post.category))];

console.log(categories); // Output: ["TypeScript", "React"]

Example 4: Imitate SQL Count with Reduce (Map)

I mostly use reduce as an alternative to SQL’s aggregate functions, such as the one below:

SELECT category, count(*)
  FROM Posts
 GROUP BY category

Which can be imitated using reduce like shown below:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const categories = posts.reduce((categories, post) => categories.set(post.category, (categories.get(post.category) ?? 0) + 1), new Map<string, number>());

categories.forEach((count, category) => console.log(`${category} (count: ${count})`));
// Output:
// "TypeScript (count: 2)"
// "React (count: 1)"

Example 5: Imitate SQL Count with Reduce (Object Props)

If needing to have the result as object properties instead of a Map, then it can be done like this:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const categories = posts.reduce(
    (categories, post) => {
        return {
            ...categories,
            [post.category]: (categories[post.category] ?? 0) + 1
        }
    },
    {} as Record<string, number>
);

console.log(categories.TypeScript); // Output: "2"

Example 6: Imitate SQL Count with Reduce (Array of Objects)

If preferring to have the result as an array of objects, then it can done like this:

const posts = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

type Category = {
    name: string,
    count: number
}

const categories = posts.reduce(
    (categories, post) => {
        const category = categories.filter(c => c.name === post.category);
        if (category.length === 0) {
            return [...categories, {name: post.category, count: 1}];
        } else {
            const c = {name: category[0].name, count: category[0].count + 1};
            return [...categories.filter(c => c.name !== post.category), c]
        }
    },
    new Array<Category>()
);
console.log(categories.length); // Output: 2

// If you want the array sorted descending
const sortedCategories = categories.sort((a, b) => b.count - a.count);
console.log(sortedCategories[0].name); // Output: "TypeScript"

Example 7: Imitate SQL Sum with Reduce

Sometimes it may also be necessary to SQL’s sum function (instead of count):

SELECT category, sum(likes)
  FROM Posts
 GROUP BY category

This can be imitated using reduce like this:

const posts = [
  {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
  {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
  {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const categories = posts.reduce((categories, post) => categories.set(post.category, (categories.get(post.category) ?? 0) + post.likes), new Map<string, number>());

categories.forEach((likes, category) => {
    console.log(`${category} (${likes} likes)`)
});
// Output: 
// "TypeScript (156 likes)"
// "React (12 likes)"

Example 8: Add TypeScript Types to Reduce

One of the things I like most about TypeScript is the compiler’s ability to automatically infer types from code; however, if wanting to add explicit types to a reduce function, then it can be done like this:

type Post = {
    id: number,
    title: string,
    category: string,
    likes: number
}

const posts: Post[] = [
    {id: 1, title: 'Clean TypeScript', category: 'TypeScript', likes: 91},
    {id: 2, title: 'Stateless React',  category: 'React',      likes: 12},
    {id: 3, title: 'Functional Core',  category: 'TypeScript', likes: 65}
];

const totalLikes = posts.reduce<number>((likes: number, post: Post) => likes += post.likes, 0);

console.log(totalLikes); // Output: "168"

Hope you liked this post and some of the examples were useful. If you know someone who might like this post, please share it😊