Here is a quick trick that I've been enjoying quite a bit. I'll start with this expression as an example of the problem:
if (x !== undefined && x !== null && x !== "" && x !== 0) {
// do something
}
If you've spent any time with JavaScript, and especially with React, you will probably have written something similar to this. Being a loosely typed language, it's often necessary to check for multiple 'falsey' types to avoid errors.
There's nothing inherently wrong with it, but it's quite wordy. In my opinion, long expressions like this make it harder to parse through a file and understand what's going on. I'm a big advocate for making code as human-readable as possible, so using multiple lines to express just one thing is a big no-no for me.
However, there is a better option!
A while ago I discovered that alongside being able to invert an expression using the NOT
!
operator, it's also possible to chain more than one of these together. This means you can evaluate any variable or expression to a boolean, so you can check if something exists using just 2 characters even if that thing could appear as multiple types.
Here's an example in React:
{!!props.heading && (
<h2>{ props.heading }</h2>
)}
In this scenario, props.heading could appear as undefined
or null
, OR it could appear as an empty string ""
.
The main problem this trick solves is that null
doesn't actually evaluate to false
on it's own: it's a unique and slightly irritating type that can cause all sorts of problems in JavaScript. Using the double NOT
operator !!
fixes this issue and avoids the need for additional expressions to check for other falsey cases.
// this wordy expression
(x !== undefined && x !== null && x !== "" && x !== 0)
// can be reduced down to this!
!!x
It's also, in my opinion, much easier to read. If I see two exclamation marks before a variable or expression, I know it's definitely checking if the variable exists. I prefer this over simply writing, { props.heading && (<>...</>) }
because with the latter example props.heading could be null
, which doesn't immediately evaluate to false
, or the string could be empty, which doesn't evaluate to false
either. This extra step ensures the data is actually useful for something before moving on while communicating to the developer that this is the intention of the expression.
// null exists in a world of its own
null === false // false
null === true // false
'' === false // false
When to avoid the double NOT operator
As useful as this little trick is, you should avoid it when working with numbers. This is because the number 0
is inherently falsey. If you're checking if the number exists, and it does exist but the number is 0
, it will think that the number doesn't exist. This might be what you want in some situations, but it's good to be aware of.
Top comments (6)
Am I missing something?
Using in your React example:
What I meant was that
console.log
will actually log0
orfalse
- the seemingly different behaviour in React is due (as you say) to what goes on with the JSX translation, and the way the value of the expression is being used byReact.createElement
:I'm filing this mentally under 'another reason to dislike JSX (as used by React)' :)
I guess it depends what you want to use it for.
I would argue that checking for truthy/falsiness is valid and it's something I use often. If a string intended for a block of content is empty, you wouldn't want to render the HTML surrounding it e.g. a h1 tag or similar, perhaps an entire section, so I find !! useful in a lot of situations where I'm conditionally rendering content. I also prefer it since it specifies the intent of the expression pretty succinctly, which is checking that the value is actually useful.
I had a look at the ?? operator which is great for defaults, but still doesn't cater for conditional content unless you want a default value over just hiding it. You could write x ?? false, but that's just !!x with more words.
Well, not quite the same -
console.log
will log0
orfalse
- React is opinionated here. It seems - as you say - a conditional operator is really the right choiceAh ok... but React wouldn't render
false
?I specified in the article that it shouldn't be used for numerical values - it's a nice way to check for falsiness, especially for null, that explicitly tells the dev what it's doing in a short format