That array.flat() and array.flatMap() stuff is great to see. Always having to rely on lodash and friends to do that type of work. Exciting to see how JS is evolving.
No this is not an alternative, it will fail if the array is too large, as you will exceed the maximum number of arguments a function will accept (which is implementation defined).
In general the spread operator should only be used for forwarding arguments not for array operations.
According to MDN `arr.flatMap()` is indeed equivalent to `arr.map().flat()` (without the Infinity). [1]
Testing in the Chrome Devtools it also seems to be the case:
Infinity was originally the default (which feels intuitive), but here's the argument for changing it [0]:
"I think Array#flatten should be shallow by default because it makes sense to do less work by default, it aligns with existing APIs like the DOM Node#cloneNode which is shallow by default, and it would align with the existing ES3 pattern of using Array#concat for a shallow flatten. Shallow by default would also align with flatMap too."
flatMap is always so unituitive (not a word) for me for some reason. I messed with it a bunch in C#'s LINQ and RxJS and I already forgot the purpose. Not sure what it is that makes it so unnatural for me.
Imagine we have a list of some values and map a function that returns a list of some other type. In other words, for every value in the list, we replace it with the results of calling our function, which returns a list. We have introduced nesting and now are operating on a "list of lists of values" rather than a list of values.
However, generally you don't want to operate on a list of lists and are trying to process each value one by one -- the nesting doesn't add anything. In this case, we use flatMap, which "flattens" or concatenates the interior lists so we can operate on them like it's just a big stream of values.
This is also the case for another type like `Optional`, which represents either a value `T` or the absence of a value. An optional can be "mapped" so that a function is applied only if there is a value `T` present. flatMap works the same way here, where if you want to call another method that also produces an `Optional`, flatMap will "unwrap" the optional since you never really want to work with the type `Optional<Optional<T>>`.
FWIW, I called the same function 'gather' in some of my code. You're producing lists of results for each member, and gathering them all together in order.
'map' as a function name isn't great either, since we have the same name for a data structure. What it has in its favor is being short and traditional.