I personally love ternary operators, and in my humble opinion, they make complicated expressions very easy to digest. Take this one:
word = (res.distance === 0) ? 'a'
: (res.distance === 1 && res.difference > 3) ? 'b'
: (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
: 'd';
However in our project's ESLINT rules nested ternary operators are forbidden, so I have to get rid of the above.
I'm trying to find out alternatives to this approach. I really don't want to turn it into a huge if / else statement, but don't know if there's any other options.
If all your truthy conditions evaluate to truthy values (so the value between the question mark and the semicolon evaluates to true if coerced to boolean...) you could make your ternary expressions return
false
as the falsy expression. Then you could chain them with the bitwise or (||
) operator to test the next condition, until the last one where you return the default value.In the example below, the "condsXXX" array represent the result of evaluating the conditions. "conds3rd" simulates the 3rd condition is true and "condsNone" simulates no condition is true. In a real life code, you'd have the conditions "inlined" in the assignment expression:
Your example could end up like below:
As a side note, I don't feel it's a good looking code, but it is quite close to using the pure ternary operator like you aspire to do...
I faced this too recently and a google search led me here, and I want to share something I discovered recently regarding this:
a && b || c
is almost the same thing as
a ? b : c
as long as
b
is truthy. Ifb
isn't truthy, you can work around it by using!a && c || b
if
c
is truthy.The first expression is evaluated as
(a && b) || c
as&&
has more priority than||
.If
a
is truthy thena && b
would evaluate tob
ifb
is truthy, so the expression becomesb || c
which evaluates tob
if it is truthy, just likea ? b : c
would ifa
is truthy, and ifa
is not truthy then the expression would evaluate toc
as required.Alternating between the
&&
and||
trick and?
and||
in the layers of the statement tricks the no-nested-ternary eslint rule, which is pretty neat (although I would not recommend doing so unless there is no other way out).A quick demonstration:
I actually cheated a bit by choosing an example where
b
is always truthy, but if you are just setting strings then this should work fine as even'0'
is ironically truthy.To my taste, a carefully structured nested ternary beats all those messy ifs and switches:
This is an older question, but this is how I would do it... I would start with the default case and then change the variable or pass it unchanged as desired.
I've been using a switch(true) statement for these cases. In my opinion this syntax feels slightly more elegant than nested if/else operators
Your alternatives here are basically:
if
/else
you don't want to doswitch
combined withif
/else
I tried to come up with a reasonable lookup map option, but it got unreasonable fairly quickly.
I'd go for #1, it's not that big:
If all the braces and vertical size bother you, without them it's almost as concise as the conditional operator version:
(I'm not advocating that, I never advocate leaving off braces or putting the statement following an
if
on the same line, but others have different style perspectives.)#2 is, to my mind, more clunky but that's probably more a style comment than anything else:
And finally, and I am not advocating this, you can take advantage of the fact that JavaScript's
switch
is unusual in the B-syntax language family: Thecase
statements can be expressions, and are matched against the switch value in source code order:How ugly is that? :-)