Javascript type coercion, truthy/falsy values and strict/loose equality

Table of contents

What is type coercion?

Type coercion in javascript is the implicit casting of data types into different ones during operations like comparisons or calculations. If and into to what a data type is coerced depends on the operation and the other data type at play, leading to some confusion. While all data types can be coerced, they can only be coerced into one of 3 primitives: boolean, string or number.

The rules of coercion

Type coercion follows a specific set of rules, making it predictable once understood:

  • + operator: If one of the variables is a string, it coerces the other into a string and performs string concatenation. If none of them is a string, it coerces both into number and performs mathematical addition.
  • Logical operators && and ||: Coerces both variables to boolean no matter what type they are
  • Loose equality operators == and !=: Coerces both variables to number unless both are string
  • Strict equality operators === and !==: Never coerce any variable. Differing data types are considered not equal.
  • All other operators always coerce both variables to number

About truthy and falsy values

Implicit type coercion with booleans may seem a bit tricky in reality, because they are treated as numbers outside of logical operators. To understand this, we first need to remember that true is equal 1 and false equal to 0 when coerced into a number. When casting other variables into boolean, the results are a little different. The following values result in false values (i.e. are falsy):

""
0
-0
NaN
null
undefined
false

These are the only values resulting in false when coerced to boolean, all other (including empty arrays and objects) are considered truthy (i.e. turn into true when coerced into boolean).

Confusion with boolean expressions

Booleans are tricky because while they behave like booleans with logical operators || and &&, they are coerced into number data types for all other comparisons.

Here is how that may be confusing:

// returns true
// because && operator coerces 4 into boolean,
// 4 is not a falsy value so it evaluates to true
4 && true // true

// returns false
// because loose equality checks coerce true into a number(1)
// and 4 isn't equal to 1
4 == true // false

// returns true
// because non-exceptional operators coerce true into number(1)
// and 4 is greater than 1
4 > true // true


// returns true
// Boolean(4) evaluates to true
// then both values are coerced into numbers (1)
// and 1 is equal to 1
Boolean(4) == true // true

If you don't want to think about edge cases like this and prefer more straight-forward operator behaviour as in most other programming languages, simply cast primitive data types manually with Number(), Boolean() and String(), and always use strict equality checks like === and !==.

More articles

Use let instead of var in javascript

And how it prevents hoisting from shooting you in the foot

You may not need jQuery

But it's not a clear cut case

Avoiding pitfalls with the net/http package in go

Prevent nasty surprises when building http server apps in go

The downsides of source-available software licenses

And how it differs from real open-source licenses

Configure linux debian to boot into a fullscreen application

Running kiosk-mode applications with confidence

How to use ansible with vagrant environments

Painlessly connect vagrant infrastructure and ansible playbooks