Ternary operators are most often used as a shorthand if-else
clause to execute code based on the
conditional expression of the ternary operator. Ternary operators can also contain any number of
nested ternary conditions to chain conditions together.
const getFee = (user) => user.isMember
? user.isFounder
? 2.00 // member and founder
: 3.00 // member not founder
: 4.00; // not a member (could technically still be a founder, but we skip that check)
Identical ternary conditions are almost always a mistake. Unless there are side effects in the test conditions identical (and equivalent) conditions necessarily result in unreachable code.
const getFee = (user) => user.isMember
? user.isMember
? 2.00
: 3.00 // unreachable code
: 4.00;
In the above example value 3.00
is unreachable code. This is due to the fact that user.isMember
cannot be true and then become false without the conditional expression having side effects.
Similarly, inverted duplicate conditions also result in unreachable code due to how nested ternary
operators work.
const getFee = (user) => user.isMember
? !user.isMember
? 2.00 // unreachable code
: 3.00
: 4.00;
By inverting the original condition we end up with same predicament however this time value 2.00
is unreachable.
This rule disallows identical ternary conditions and duplicate inverted ternary conditions within nested ternary expressions no matter how far or where they are nested.
It will also detect and report equivalent or conditions, for example x || y
is logically
equivalent to y || x
.
Examples of incorrect code for this rule:
/*eslint no-unreachable: "error"*/
const getFee = (user) => user.isMember ? user.isMember ? 2.00 : 3.00 : 4.00;
// 3.00 is unreachable
const thing = condition1 || condition2 ? condition2 || condition1 ? 'x' : 'y' : 'z';
// 'y' is unreachable
const getFee = (user) => user.isMember ? 3.00 : user.isMember ? 2.00 : 4.00;
// 2.00 is unreachable
const result = foo(x) ? !foo(x) ? 1 : 2 : 3;
// 1 is unreachable
const formula = condition1 && condition2
? condition2
? `${oldRate}+${User.fee}`
: `${currentRate}+${User.fee}`
: `${newRate}+${User.fee}`;
// `${currentRate}-${User.fee} is unreachable`
condition1 ? foo() : condition2 ? bar() : condition3 ? baz() : condition1 ? qux() : bar());
// qux() is unreachable
Examples of correct code for this rule:
/*eslint no-unreachable: "error"*/
const getFee = (user) => user.isMember ? user.isFounder ? 2.00 : 3.00 : 4.00;
const thing = condition1 || condition2 ? condition2 ? 'x' : 'y' : 'z';
// This nested ternary won't error by default. While this pattern is uncommon it does not result in
// unreachable code. See option details below.
const formula = condition1
? condition2
? `${oldRate}+${User.fee}`
: `${currentRate}+${User.fee}`
: `${newRate}+${User.fee}`;
condition1 ? foo() : condition2 ? bar() : condition3 ? baz() : condition4 ? qux() : bar());
This rule has an object option:
"allowDuplicateOrConditions": true
(default) allows duplicate OR type ternary conditions if the expression does not result in unreachable code"allowDuplicateOrConditions": false
(recommended) disallows OR type ternary conditions from appearing more than once inside the ternary chain (no matter how far nested)
When set to true, which it is by default, the allowDuplicateOrConditions option allows expressions
in the form of condition1 || condition2 ? condition2 || condition3 ? x : y : z;
even though this
could be shortened to condition2 ? condition1 || condition3 ? x : y : z
.
Examples of correct code for this rule with the { "allowDuplicateOrConditions": true}
option:
/*eslint no-unreachable: ["error", { "allowDuplicateOrConditions": true }]*/
const thing = condition1 || condition2 ? condition2 || condition3 ? 'x' : 'y' : 'z';
const otherThing = condition1 || condition4 ? condition2 ? condition3 || condition4 ? 'w' : 'x' : 'y' : 'z';
By setting allowDuplicateOrConditions option to false
the above code would error with Duplicate ternary OR conditions {{condition}}.
.
Please note the difference in the error message from the standard Equivalent ternary OR conditions {{condition}}.
.
Examples of incorrect code for this rule with the { "allowDuplicateOrConditions": false}
option:
/*eslint no-unreachable: ["error", { "allowDuplicateOrConditions": false }]*/
const thing = condition1 || condition2 ? condition2 || condition3 ? 'x' : 'y' : 'z';
// Error: Duplicate ternary OR conditions 'condition2'.
const otherThing = condition1 || condition4 ? condition2 ? condition3 || condition4 ? 'w' : 'x' : 'y' : 'z';
// Error: Duplicate ternary OR conditions 'condition4'
Examples of correct code for this rule with the { "allowDuplicateOrConditions": false}
option:
/*eslint no-unreachable: ["error", { "allowDuplicateOrConditions": false }]*/
const thing = condition1 ? condition2 || condition3 ? 'x' : 'y' : 'z';
const otherThing = condition1 ? condition2 ? condition3 || condition4 ? 'w' : 'x' : 'y' : 'z';
This rule will never report inverted conditions that also form part of a ternary OR expression:
const result = condition1 || condition2 ? !condition1 ? x : y : z;
This, again, technically does not result in unreachable code despite being an uncommon coding pattern.
In rare cases where you really need identical ternary conditions in the same chain, which necessarily means that the expressions in the chain are causing and relying on side effects, you will have to turn this rule off.