-1

Give this code in TypeScript:

const res = arr.reduce((acc, cur) => (cur.id ? ++acc : acc), 0);

How do I stop the linter throwing these two errors?

(parameter) acc: number Unary operator '++' used. eslint no-plusplus

Assignment to function parameter 'acc'. eslint no-param-reassign

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Mr. Robot
  • 1,334
  • 6
  • 27
  • 79

1 Answers1

2

A reduce callback accepts an accumulator and the current value as arguments and returns the accumulator for the next iteration, or the accumulator as a result if there is no next iteration. There is no reason to mutate any of the arguments.

There are a few arguments in favor of avoiding mutating parameters in general, and that’s why ESLint complains about this, with the no-param-reassign rule.

The no-plusplus rule, additionally, disallows syntax like ++acc.

Since there is no need to mutate acc to begin with, the minimal fix for both errors would be:

   const res = arr.reduce((acc, cur) => (cur.id ? acc + 1 : acc), 0);
//                                                ~~~~^~~              Replace `++acc` by `acc + 1`

This returns acc incremented by 1 if cur.id is truthy, and the current acc, otherwise, as expected. Your version mutates the current acc in addition to returning the incremented acc, but there is no reason to do so.


If you’re using ESLint, you have to be aware of the rules. You can’t write code that ESLint complains about and then be confused why ESLint complains about your code. Every rule has its own article explaining the rationale, listing alternatives, and explaining how the rule can be adjusted or disabled.

For example, you can disable the no-param-reassign rule

  • by including the comment // eslint-disable no-param-reassign at the top of your file,
  • or // eslint-disable-next-line no-param-reassign one line above a usage,
  • or // eslint-disable-line no-param-reassign in the line after a usage,
  • or by disabling it in your .eslintrc file.

There’s also a rule that would disallow conditional expressions and some variants. You can further simplify your function to avoid even that:

const res = arr.reduce((acc, cur) => acc + Number(Boolean(cur.id)), 0);

This would have the same semantics, but it’s still not quite clear what kind of condition cur.id was supposed to be. It’s best practice to make that a little more explicit (especially in TypeScript), e.g. cur.hasOwnProperty("id") or cur.id !== 0 or cur.id !== "", depending on what cur.id may be. Then, the Boolean call is no longer necessary; for example, if you want to count how many objects in arr have an id own property, use this instead:

const res = arr.reduce((acc, cur) => acc + Number(cur.hasOwnProperty("id")), 0);

or this:

const res = arr.filter((cur) => cur.hasOwnProperty("id")).length;

If you still want to use your original falsy / truthy check, the code can be shortened to one of these, using destructuring assignment:

const res = arr.reduce((acc, {id}) => acc + Number(Boolean(id)), 0);
const res = arr.filter(({id}) => id).length;
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75