Reputation: 49714
I've recently added the eslint rule no-param-reassign
.
However, when I use reduce
to build out an object (empty object as initialValue
), I find myself needing to modify the accumulator
(first arg of callback function) on each callback iteration, which causes a no-param-reassign
linter complaint (as one would expect it would).
const newObject = ['a', 'b', 'c'].reduce((result, item, index) => {
result[item] = index; // <-- causes the no-param-reassign complaint
return result;
}, {});
Is there a better way to build out an object with reduce
that doesn't modify the accumulator
argument?
Or should I simply disable the linting rule for that line in my reduce
callback functions?
Upvotes: 66
Views: 30040
Reputation: 4087
As I found no other reasonable solution, I just disable that single check:
const newObject = ['a', 'b', 'c'].reduce((result, item, index) => {
// eslint-disable-next-line no-param-reassign
result[item] = index;
return result;
}, {});
Upvotes: 3
Reputation: 1024
Whenever I use Array.prototype.reduce
I always name the "accumulator" parameter accu
. This convention conveniently allowed me to set my eslint rule:
"no-param-reassign": [
"error",
{
"props": true,
"ignorePropertyModificationsFor": ["accu"]
}
],
If you have your own naming convention for this parameter, replace "accu" in the rule above with whatever you use, and eslint will not complain about modifying your accumulator.
Upvotes: 34
Reputation: 49714
One solution would be to leverage the object spread operator
const newObject = ['a', 'b', 'c'].reduce((result, item, index) => ({
...result,
[item]: index,
}), {});
Performance Warning!! This is a non-performant (O(n^2
) solution that should be avoided.
Upvotes: 34
Reputation: 2935
I just wrap the reduce functions in a lint rule disable block, ie:
/* eslint-disable no-param-reassign */
const newObject = ['a', 'b', 'c'].reduce((result, item, index) => {
result[item] = index;
return result;
}, {});
/* eslint-enable no-param-reassign */
Upvotes: 38
Reputation: 664444
Well, you could do (result, item) => Object.assign({}, result, {[item]: whatever})
to create a new object on every iteration :-)
If you want to trick the linter, you could use => Object.assign(result, {[item]: whatever})
(which does the same as your current code but without an explicit assignment), but yeah I guess you should simply disable that rule.
Upvotes: 11