What is type coercion?
Explicit coercion is when you type cast a value from one type to another through the use of functions like Number() and String().
String(42) // "42" String(undefined) // "undefined" Number("12") // 12 Number("abc") // NaN Number(undefined) // NaN Boolean(0) // false Boolean(1) // true Boolean(10) // true
Since type casting is something found in most programming languages, I won’t be talking much about it.
The rest of the post will be on implicit coercion.
Terms to get out of the way
Here are some terms that will be used in the post you should understand.
- assignment operators ( =, +=, -=, etc)
- comparison operators (==, ===, !=, etc)
- arithmetic operators (+, -, *, /, etc)
- logical operators ( &&, ||, !, etc)
Values that operators work on are called operands.
2 + 5
In this expression, 2 and 5 are operands.
Alright, with those terms out of the way, let’s talk about implicit coercion!
Strings and Numbers
When you use arithmetic operators on two values of type String and Number, often one will be converted to the other.
'1' + 2 // '12' '12' - 2 // 10
This begs the question: what if you perform subtraction or division (operations that only make sense on numbers) on strings? Well, that would cause the NaN value to be returned, which literally stands for ‘Not a Number’.
Truthy and Falsey: What boolean some values are converted to
Truthy values are values that are implicitly converted to true, while falsey values are values that are implicitly converted to false.
- Any number that is not zero
- Any non-empty string
Falsey Values – the catch-all
// only execute code if value is not undefined or null if (!!value): // code
You might have seen this used to catch undefined and/or null values. This works because undefined and null are falsey values, meaning they are implicitly coerced to the boolean false.
- 0 and -0
- “” and ”
While it looks clean to use !!value to prevent undefined, null, and other values that imply “nothingness” to execute certain code, it can cause some bugs that are hard to pinpoint.
Notice how 0 and empty strings are falsey? This means that if value is 0 or an empty string, the code nested in the if statement will not be executed.
Hence, it is often better to use the equality operator to check if a value is null or undefined like so:
// only execute code if value is not undefined or null if (value != undefined && value != null): // code
Expressions with comparison operators don’t have to return a boolean
When the expression is evaluated, the operands are interpreted as booleans through implicit coercion. However, what gets returned is the value itself, not what the operand equates to when converted to a boolean.
Take this for example:
1 || false
When the expression is evaluated, 1 is interpreted as true through implicit coercion, but that 1 itself is returned as opposed to the boolean it was converted to.
How the return value is determined (when both operands are coerced to the same boolean)
When you have an || operator with at least one truthy value, the first truthy value (from left to right) is returned. Otherwise, if both values are falsey, the last value is returned.
This allows you to do this:
value = value || “default value”
If value originally is falsey, it will be coerced to false when the expression is evaluated, and thus the string “default value”, which coerces to true, is assigned to value.
Another example you might have come across in Express:
const PORT = process.env.PORT || 5000; app.listen(PORT);
Since in development the process.env.PORT environment variable is undefined, 5000 is assigned to PORT.
In production, process.env.PORT has a value. Thus, it is set to PORT as it is the first truthy value in the expression. This allows the app to listen on a different port on production and development environment.
When you have an && operator with at least one falsey value, the first falsey value (from left to right) is returned. Otherwise, if both values are truthy, the last value is returned
Checking for Equality
When you want to check if two values are equal, most of the time you do not want type coercion to occur – you want to compare them exactly the way they are. That is why you should always use the strict equality operator === to check if two values are equal (unless you intentionally want coercion to take place) and !== to check if they aren’t equal.
12 == '12' // true 12 === '12' // false false == 0 // true false === 0 // false null == undefined // true null === undefined // false
As you can see, you should avoid using == and != (or ‘evil twins’, as Douglas Crockford calls them) if you can.
You can find an extensive equality table with == here.
Found this helpful? Share with you friends! Comment if there is anything you felt could be better in this post.