eslint-plugin-unicorn
eslint-plugin-unicorn copied to clipboard
Rule proposal: `prefer-array-map`
Description
Often no-for-loop
results in something that could be simplified down to usage of Array.prototype.map()
This is an alternative to https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1714 and only one of these rules should be implemented.
I would only allow this rule to match only "simple" for..of
cases as in these examples.
Fail
const result = []
for (const element of array) {
result.push(transform(element))
}
const result = []
for (const [index, element] of array.entries()) {
result[index] = transform(element)
}
const result = []
for (const [index, element] of array.entries()) {
result.push(anotherArray[index](element))
}
Pass
const result = array.map((element) => transform(element))
const result = array.map((element, index) => anotherArray[index](element))
Hmm, this rule could be problematic for stuff beyond arrays. for..of isn't just for arrays, its generally for iterables https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
So this transformation is only valid if we know x
in for (... of x) {
is an Array
I would wait on https://github.com/tc39/proposal-iterator-helpers
This should work for for..await..of
, once Array.fromAsync
is ready.
@fisker interesting. maybe that's a different rule, prefer-array-from
and uses https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
the neat thing about that is it has a built in map function, so it already works for both arrays and iterators.
related is prefer-spread
which transform Array.from
to spread
I think I'm against this. for..of
is generally superiour because it allows flow control statements. Array#map
has its uses for simple one-liners, but I would not recommend it in the general sense as a replacement of for..of
.
Found one in our codebase
https://github.com/sindresorhus/eslint-plugin-unicorn/blob/ba9d53cd522e641d9b8da7ce495ed0110b8ce33a/test/package.mjs#L100-L111
Another case if there is more than 1 argument in Array#push
method, should be reported by prefer-array-flat-map
.
One exception: when the loop content accesses the array for other reasons (e.g. to look back). Random example:
const result = [];
for (const item of array) {
if (result.includes(item)) { // `result` array access
console.error('Found duplicate!!11')
} else {
result.push(item * 2)
}
}
@fregante yep, the rule wouldn't apply in this case as it access the result before .map
completes. However, that example could be rewritten as an .reduce
I would only allow this rule to match only "simple"
for..of
cases as in these examples.
Maybe a single condition could also be wrapped. From:
const result = []
for (const element of array) {
if (element > 4)
result.push(transform(element))
}
to:
const result = array
.filter(element => element > 4)
.map((element) => transform(element))