Unlike other programming languages, JavaScript does not have static typing: values can be coerced into a different value type at runtime, leading to unexpected results. But what does all this even mean?
Table of contents
Open Table of contents
What the heck is type coercion?
Type coercion is the implicit conversion of a value from one data type to another. It occurs in JavaScript because it’s a dynamically typed language: value types are not declared explicitly, but inferred by the interpreter at runtime.
Because of this feature, when values of different data types are compared or used together in an expression, some of them may be implicitly coerced into another data type.
Kinds of type coercion
Let’s now take a look at the main kinds of type coercion in JavaScript!
Number (and other value types) to String coercion
When a non-string value is added (or rather, concatenated) to a string by using the +
operator, the non-string value is coerced into the string data type.
const a = '5';
const b = 9; // coerced to string '9'
const result = a + b;
console.log(result);
// "59"
const a = '5';
const b = 9; // coerced to string '9'
const result = b + a;
console.log(result);
// "95"
Although many examples of this type of coercion can be found with number values, it can also occur with other value types:
const a = '5';
const b = true; // coerced to string 'true'
const result = a + b;
console.log(result);
// "5true"
String to Number coercion
When using the -
, *
, /
or %
operators, any value that is not a number is coerced into the number data type. This is because these operations can only be performed between numbers.
const a = 10;
const b = '5'; // coerced to number 5
const result = a - b;
console.log(result);
// 5
Boolean to Number coercion
When a boolean is added to a number, the boolean value is coerced into a number, since it’s safer and easier than the other way around.
const a = true; // coerced to number 1
const b = 2;
const result = a + b;
console.log(result);
// 3
const a = false; // coerced to number 0
const b = 2;
const result = a + b;
console.log(result);
// 2
The equality operators
Type coercion does not only happen when performing operations with different value types: it also occurs when we compare them.
Loose type equality
Comparing values with the ==
or !=
operators uses implicit type coercion. As a result, any non-number value will be coerced into the number data type, and then compared. Only the final coerced values will be compared, and not their type.
const a = 10;
const b = '10'; // coerced to number 10
console.log(a == b);
// true
const a = true; // coerced to number 1
const b = 1;
console.log(a == b);
// true
const a = true; // coerced to number 1
const b = 'true'; // coerced to NaN
console.log(a == b);
// false
const a = null; // coerced to number 0
const b = undefined; // coerced to number 0
console.log(a == b);
// true
Strict type equality
Comparing values with the ===
or !==
operators does not use implicit type coercion. It will always compare not only the values, but also their data type.
Using these operators helps us avoid unexpected type coercion that may lead to errors in our code.
const a = 10;
const b = '10';
console.log(a === b);
// false
const a = true;
const b = 1;
console.log(a === b);
// false
const a = true;
const b = 'true';
console.log(a === b);
// false
const a = null;
const b = undefined;
console.log(a === b);
// false
Explicit type conversion
Type coercion is different from type conversion, which can be implicit or explicit. We can explicitly convert a value into a data type by using the constructor function of that data type: Number()
, String()
or Boolean()
.
const a = '5';
console.log(Number(a));
// 5
Recap
Let’s review the main ideas we’ve learned in this post:
- JavaScript is a dynamically typed language: we don’t define the value types explicitely, therefore they are inferred at runtime.
- Type coercion occurs when a value type is implicitely converted into another.
- Using the strict equality operators (
===
and!==
) is recommended to avoid errors. - Type conversion can be implicit of explicit. We explicitely convert a value into another data type by using the appropriate constructor function.
Bonus
We’ve mainly discussed about how type coercion works with primitive types. If you want to dig deeper into the topic, here are a couple of articles that also go over how non-primitive types (mainly arrays and objects) are coerced:
- More complex examples explained
- How JavaScript abstract operations work under the hood and result in implicit type coercion
That’s it for today! I hope you have a better idea of how type coercion works in JavaScript, and use this knowledge to avoid or debug errors when you find them :D