How can I avoid nested ternary expressions in my code?

Viewed 26029

I have code like this. How can I write it in cleaner, more elegant way using functional programming in JavaScript? I want to get rid of nested ternary expressions. Any ideas?

props => ({
            iconColor: props.isPriority ? (props.isCompleted ? variables.color.lightpurple : variables.color.purple ) : variables.color.gray3,
            iconName: props.isPriority ? 'star-full' : 'star-empty',
          }))

This is rest of that code:

EDIT:

const enhance: React$HOC<*, InitialProps> = compose(
      withProps(props => ({
        iconColor: props.isPriority ? (props.isCompleted ? variables.color.lightpurple : variables.color.purple) : variables.color.gray3,
        iconName: props.isPriority ? 'star-full' : 'star-empty',
      }))
    )
5 Answers

Yes, but my linter is not happy: 44:16 error Do not nest ternary expressions [no-nested-ternary]

If that's your only problem then the solution is simple. Create your own conditional function:

const iff = (condition, then, otherwise) => condition ? then : otherwise;

props => ({
  iconColor: props.isPriority ?
    iff(props.isCompleted, variables.color.lightpurple, variables.color.purple) :
    variables.color.gray3,
  iconName: props.isPriority ? 'star-full' : 'star-empty',
})

Now your linter shouldn't complain. That being said, you should disable [no-nested-ternary] in your linter. It's kind of stupid that your linter thinks that nested conditionals are bad.

In this case you could consider inverting the condition to remove the "unnatural" nesting of ternaries. There would still be nesting, but it can be written flat - without parentheses - which means that you can lay it out neatly across multiple lines:

props => ({
    iconColor:
        !props.isPriority ? variables.color.gray3
        : props.isCompleted ? variables.color.lightpurple
        : variables.color.purple,
    iconName: props.isPriority ? 'star-full' : 'star-empty',
})

The downside of this is use of a negative condition, which I usually try to avoid as they're a bit harder to follow than positive conditions.

Yet another option is to flatten the conditions with &&:

props => ({
    iconColor:
        props.isPriority && props.isCompleted ? variables.color.lightpurple
        : props.isPriority ? variables.color.purple
        : variables.color.gray3,
    iconName: props.isPriority ? 'star-full' : 'star-empty',
})

I will suggest, simply use below:

    props => ({
      iconColor: ${(props) => {
      if (props.isPriority) {
        return props.isCompleted
          ? variables.color.lightpurple
          : variables.color.purple;
      }
      return variables.color.gray3;
    }};
      iconName: props.isPriority ? 'star-full' : 'star-empty',
    })
Related