Booleans are an intrinsic, crucial part of software. Any time we need to conditionally execute code, our condition will be a boolean; or converted into one. Sometimes we may want to store such a value to, for example, send it to a client or store it in a database.
To accomplish that, most statically-typed languages, like Rust or Java,
require us to explicitly convert a value to a boolean. A condition, such
as whether a user is an administrator, is turned into a boolean by using
an operator like the equals operator (==
).
boolean isAdmin = user.role == Roles.ADMIN;
In some dynamically-typed languages like JavaScript, any value can be
converted into a boolean. JavaScript introduces the concept of truthy and
falsy values, which can be converted into true
and false
respectively. Therefore, we can use values as booleans by letting
JavaScript implicitly convert (i.e. coerce) them instead of having to
convert them with an operator ourselves, making our code more concise.
// Java
if (user != null) {
}
// JavaScript
if (user) {
}
JavaScript, as I’ve pointed out in a previous post about the double tilde operator, is a magical and wondrous programming language. One of these wondrous things is its type coercion system, including boolean coercion. If you’ve written JavaScript for some time, you might’ve encountered the double bang operator already. This operator is denoted with two exclamation marks followed by an expression.
const hasPhoneNumber = !!user.phoneNumber;
Technically, the double bang operator performs a logical double negation
on the expression. Double-negating truthy and falsy values, including
true
and false
themselves, result in true
and false
respectively.
That makes the double bang operator a shorthand for coercing any value
into a boolean.
The double bang is used rarely because booleans are mostly used in
if
-conditions, where—as demonstrated above—we can use any value and
JavaScript will automatically convert into a boolean for us. Adding !!
in front of a condition is redundant since that doesn’t change the
behavior of the code.
Instead, the double bang is mostly used where we want to explicitly
convert a value into a boolean. Now, let’s suppose we run a forum and
wrote an API that checks whether a given user name is already taken. We
could do that by reusing an existing method like getUserByName(name)
and sending the returned user object to the client.
Hopefully it’s obvious that this is a bad idea. What if the user object
contains a (hashed) password or other secrets? Simple solution: we add
the double bang operator to it. Then, !!getUserByName(name)
will
respond with true
if the user with the given name exists and false
otherwise.
While there are actually many ways to convert a value to a boolean in
JavaScript, the only other reasonably competing way is using the
Boolean() function
. Under the hood, both the double bang
and Boolean
function execute the low-level
ToBoolean
operation, which handles the boolean conversion.
Unlike the double tilde operator
and the Math.floor
function, there’s no functional difference
between these two ways of boolean conversion. And according to Arthur
Visser’s post about this subject, there’s no significant
performance difference either.
return !!(user.email && user.verified_at);
return Boolean(user.email && user.verified_at);
// or for functional predicates
array.filter((item) => !!item);
array.filter(Boolean);
I used to like the double bang for how concise it made my code, except
for predicates. However, this conciseness comes at the cost that double
negation is often understood as something to be introduced, and more
often, eliminated for a logical proof. But the statement a ≡ !!a
, with
≡
being strict equality and !
negation, is not true in JavaScript
because non-booleans can be negated and thereby converted into a boolean.
More importantly, and less abstract than a mathematical nitpick, the
double bang—just like the double tilde—is a smartass way to
solve a problem. It needs explaining where a type conversion of
Boolean(a)
doesn’t. It’s an interesting quirk of JavaScript, though
more useful in code minimization.
If you value readability and maintainability of your code, and don’t
already use Boolean()
, consider using it instead of the double bang.
Your future self not having to explain it to junior colleagues will thank
you for it.