codingpaws

The double bang in JavaScript

Apr 08, 2023 · 3 min read

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.