sfletche
sfletche

Reputation: 49714

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?

Upvotes: 66

Views: 30040

Answers (5)

vault
vault

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

Anj
Anj

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

sfletche
sfletche

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

Zack Knopp
Zack Knopp

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

Bergi
Bergi

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

Related Questions