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;
falsy values, which can be converted into
respectively. Therefore, we can use values as booleans by letting
convert them with an operator ourselves, making our code more concise.
const hasPhoneNumber = !!user.phoneNumber;
Technically, the double bang operator performs a logical double negation
on the expression. Double-negating truthy and falsy values, including
false themselves, result in
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
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
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,
true if the user with the given name exists and
While there are actually many ways to convert a value to a boolean in
Boolean() function. Under the hood, both the double bang
Boolean function execute the low-level
ToBoolean operation, which handles the boolean conversion.
Unlike the double tilde operator
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
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
If you value readability and maintainability of your code, and don’t
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.