JavaScript flatMap

Map and Flatten in One Pass


The flatMap method combines two things we do with arrays all the time, mapping over the items and flattening the result, into a single call. Instead of writing array.map(fn).flat() and looping over the array twice, flatMap does both passes in one, which is the small readability win it is best known for.

We will look at how flatMap behaves with a simple example first, and then use it to solve a filtering problem that usually makes people reach for map and filter together.

How it Works

flatMap takes a callback just like map does, but if that callback returns an array, the result gets flattened by one level automatically.

const numbers = [1, 2, 3]

const doubled = numbers.flatMap(n => [n, n * 2])

console.log(doubled) // [1, 2, 2, 4, 3, 6]

Here we return a pair for every number in the array. With a regular map we would end up with an array of arrays, something like [[1, 2], [2, 4], [3, 6]]. flatMap flattens that one level down for us, so we get a single flat list back without a separate .flat() call after it.

Filtering while mapping

One place flatMap actually saves you code is when you want to map and filter at the same time. Returning an empty array from the callback works like skipping that item entirely.

const orders = [
  { id: 1, total: 40 },
  { id: 2, total: 0 },
  { id: 3, total: 120 },
]

const totals = orders.flatMap(order => (order.total > 0 ? [order.total] : []))

console.log(totals) // [40, 120]

We map each order to its total, but for the order with a total of 0 we return an empty array instead of a number. Since flatMap flattens whatever the callback returns, that empty array just contributes nothing to the final list, so there is no need for a filter call before or after the map.

Conclusion

flatMap will not replace map and filter everywhere, most of the time using them separately is still clearer to read. But when you catch yourself chaining .map().flat(), or reaching for filter right after a map just to drop a few items, flatMap usually gets you the same result in one pass and one line.

Thanks!!

Comments