Iterator.prototype.flatMap()

Map each value to an iterable and yield the inner values inline, flattening one level lazily.

Signature
flatMap(callbackFn)
  • Added in JavaScript ES2025 (Baseline March 2025)

Parameters

ParameterTypeDescription
$callbackFnFunctionCalled for each element as callbackFn(element, index). Must return an iterator or an iterable whose elements are yielded by the helper. element is the current value and index is its zero-based position.

Return value

Iterator HelperA new iterator helper object that yields, one by one, the elements of each iterator or iterable returned by callbackFn, moving on to the next source element when the current inner sequence is exhausted.

Errors

Throws a TypeError if callbackFn is not callable, or if its return value is neither an iterator nor an iterable — notably including a string primitive, which is rejected even though strings are iterable.

flatMap() is map() for one-to-many transforms. The callback returns a sequence rather than a single value, and the helper splices that sequence into the output as if by yield*. Returning an empty array drops the element entirely, which makes it a combined map-and-filter in one pass.

When to reach for it

  • Splitting each item into several — lines into words, records into their child records.
  • Expanding a tree or grouped structure into a flat stream of leaves.
  • Transforms that sometimes produce nothing: return [] to skip, [value] to keep.

What trips people up

It flattens exactly one level, and only the level the callback returns. Nested arrays inside the returned iterable stay nested; there is no depth argument as there is on Array.prototype.flat().

The sharpest edge is strings. A string is iterable, so intuition says returning one should spread it into characters — but the specification explicitly rejects string primitives and throws a TypeError. Wrap it: return [str] to yield the whole string, or str.split("") to yield characters.

Laziness is preserved: inner sequences are pulled only as far as the consumer demands, so an inner infinite generator is fine as long as something downstream stops.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Split each line of text into words in a single lazy pass
  • Flatten team objects into a stream of their member names
  • Emit zero or more results per input by returning an empty or multi-element array

Frequently asked questions

How deep does flatMap() flatten?

Exactly one level — the sequence the callback returns is spliced in, but anything nested inside it stays nested. There is no depth parameter like Array.prototype.flat() has. To go deeper, chain a second flatMap() or write a recursive generator that uses yield*.

Why does returning a string throw a TypeError?

The specification deliberately rejects string primitives to prevent the common bug of accidentally spreading a word into single characters. If you want the whole string as one value, return [str]; if you really do want characters, return str.split("") or Array.from(str).

Can flatMap() be used to filter as well as map?

Yes. Return an empty array to drop an element and a one-element array to keep it, which fuses the two operations into one pass. It is the idiomatic way to express a transform that sometimes fails: return [] when parsing fails and [parsed] when it succeeds.

More examples

Expanding nested records, empties included

The empty members array contributes nothing to the output, so the blue team simply vanishes from the result — no undefined placeholder, unlike map().

Example · javascript
const teams = [
  { name: "red", members: ["ann", "bo"] },
  { name: "blue", members: [] },
  { name: "green", members: ["cy"] },
];

console.log(teams.values().flatMap((t) => t.members).toArray());
// ["ann", "bo", "cy"]

Returning a generator from the callback

The callback may return any iterator, not just an array. Each generator is consumed to completion before the next source element is pulled, which is what makes the run-length expansion come out in order.

Example · javascript
function* repeat(value, times) {
  for (let i = 0; i < times; i++) yield value;
}

const runs = [["a", 3], ["b", 1], ["c", 2]];

console.log(
  runs.values().flatMap(([ch, n]) => repeat(ch, n)).toArray(),
); // ["a", "a", "a", "b", "c", "c"]

Discussion

  • Be the first to comment on this lesson.