Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle eslint no-param-reassign rule in Array.prototype.reduce() functions

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?

like image 586
sfletche Avatar asked Jan 13 '17 00:01

sfletche


4 Answers

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.

like image 129
sfletche Avatar answered Oct 25 '22 20:10

sfletche


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 */
like image 28
Zack Knopp Avatar answered Oct 25 '22 18:10

Zack Knopp


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.

like image 20
Anj Avatar answered Oct 25 '22 20:10

Anj


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.

like image 11
Bergi Avatar answered Oct 25 '22 18:10

Bergi