In JS/TS, I occasionally see people excited about writing "functional" code write code like the following:

const schools_by_id = schools.reduce((acc, school) => {
    acc[school.school_id] =  school;
    return acc;
}, {} as Record<string, School>);

Personally, I find this "functional" style hard to read! The first time I encounter acc, I'm unsure of what it even is and then it needs to be returned? It takes me a second to parse even a simple reduce like this one.

I find a for loop much easier to read:

const schools_by_id: Record<string, School> = {};
for (const school of schools) {
    schools_by_id[school.school_id] = school;
}

Sure, we're mutating data, but it's local. This isn't the kind of data mutation that's going to cause a problem—it's exactly the same mutation that we're doing in the reduce.[1] And a for loop makes some code much easier to work with—if we want to skip a row, we can continue and if we need to make this code async, we can just add await.

If we wanted to write this code in a functional way, we should do so by writing (or importing) utilities that describe what we want to happen rather than describing how it should happen.

// https://lodash.com/docs/4.17.15#keyBy
const schools_by_id = _.keyBy(schools_by_id, school => school.school_id)

How much easier is this to read than the schools.reduce version?

And I know you might not need lodash, but you'll probably want your own versions of some of lodash's utilities if you're doing any sort of data transformation. I don't use most of lodash's functions, but if I were dropped into a code-base that didn't have its own versions of _.keyBy, _.groupBy, _.mapValues, _.partition, and _.orderBy, I'd probably want to add them.[2]

Listening to me gripe about .reduce isn't likely to convince anyone. Try searching your code-base for .reduce! What do you think? Would they be better as for loops? Or using utility functions?

When I do this in code-bases I work in, I see a few good examples of code that is clearer because of .reduce, but the vast majority of the code I see could be clearer if it were rewritten.


  1. Unless someone has written an abomination like const school_by_id = schools.reduce((acc, school) => ({...acc, [school._id]: school}), {}). That code is slow and unclear for no good reason. ↩︎

  2. It's worth noting that lodash doesn't tree-shake well, so if you're working on the frontend, it may make sense to stick plain javascript versions of the utilities you want into a utility file. https://youmightnotneed.com/lodash ↩︎