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

JavascriptEcmascript 6Eslint

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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 */

Solution 3 - Javascript

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.

Solution 4 - Javascript

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsfletcheView Question on Stackoverflow
Solution 1 - JavascriptsfletcheView Answer on Stackoverflow
Solution 2 - JavascriptZack KnoppView Answer on Stackoverflow
Solution 3 - JavascriptAnjView Answer on Stackoverflow
Solution 4 - JavascriptBergiView Answer on Stackoverflow