Rule proposal: no-confusing-conditions
mmkal opened this issue · comments
Description
It's hard to look at conditions with mixed &&
and ||
operators and intuitively remember 3,712 words on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence. There should be a rule that forces you to use parentheses for clarity and readability, even when to the JS engine, it's unambiguous.
Fail
a && b || c;
a || b * c;
a && b < c;
a ?? b || c;
Pass
Explicit parens (not auto-fixable) are ok:
a && (b || c);
a || (b * c);
a && (b < c);
a ?? (b || c);
The rule shouldn't have an opinion on where parens are ok
(a && b) || c;
(a || b) * c;
(a && b) < c;
(a ?? b) || c;
Chained operators should be ok:
a && b && c
a || b || c
a ?? b ?? c
Familiar maths expressions taught to schoolchildren (BODMAS/PEMDAS) shouldn't be punished:
a ** b + c
a - b / c
a * b ** c
Additional Info
It should probably be implemented in a way such that all expressions with more than one operator are flagged, unless they are known to be OK, so that any missed cases are assumed to be needing-parentheses.
Rough allowlist implementation off the top of my head:
const mathsOperators = new Set(['+', '-', '*', '/', '**'])
const isok =
operators.length <= 1
|| operators.every(op === operators[0])
|| operators.every(op => mathsOperators.has(op))
But implementing and testing would probably reveal more cases where it's not ambiguous, and not worth the extra verbosity.
Having written all that, I did find https://eslint.style/rules/js/no-mixed-operators - I'm not sure what the policy is on rules that exist elsewhere, there's other overlap between eslint-plugin-unicorn and @stylistic/eslint-plugin-js so maybe worth adding here too? I didn't actually know @stylistic/eslint-plugin-js
existed, so not sure what the policy is.
I'm not sure what the policy is on rules that exist elsewhere, there's other overlap between eslint-plugin-unicorn and @stylistic/eslint-plugin-js so maybe worth adding here too? I didn't actually know @stylistic/eslint-plugin-js existed, so not sure what the policy is.
If we could make a rule better, it may make sense sometimes, but in this case, you should just use no-mixed-operators
.