Type Coercion & Comparison

Difficulty: Intermediate

Question

Explain type coercion in JavaScript. What are the rules for == vs === and truthy/falsy values?

Answer

Type coercion is JavaScript's automatic conversion of values from one type to another. It happens in two contexts: implicit coercion (triggered by operators and comparisons) and explicit coercion (using functions like Number(), String(), Boolean()).

The == operator performs type coercion before comparison, while === (strict equality) does not - it requires both value AND type to match. The == rules are complex: null == undefined is true, numbers are compared numerically, and objects are converted with valueOf/toString.

There are exactly 8 falsy values in JavaScript: false, 0, -0, 0n (BigInt zero), '' (empty string), null, undefined, and NaN. Everything else is truthy, including empty objects {}, empty arrays [], and the string 'false'.

Understanding coercion is essential because it causes many subtle bugs, especially with ==, + (concatenation vs addition), and if conditions.

Code examples

== vs === and Coercion Rules

// Strict equality - no coercion
console.log(1 === '1');    // false (different types)
console.log(1 === 1);     // true
console.log(null === undefined); // false

// Loose equality - with coercion
console.log(1 == '1');    // true (string -> number)
console.log(true == 1);   // true (boolean -> number)
console.log(null == undefined); // true (special rule)
console.log(null == 0);   // false (null only == undefined)
console.log('' == false);  // true (both -> 0)

// Surprising results
console.log([] == false);  // true ([] -> '' -> 0, false -> 0)
console.log([] == ![]);    // true ([] -> 0, ![] -> false -> 0)
console.log('' == 0);     // true
console.log(' \t\n' == 0); // true (whitespace string -> 0)

== coerces types before comparing. The rules are: null == undefined, string/boolean convert to number, objects convert via valueOf/toString. Always use === to avoid surprises.

Truthy/Falsy Values

// All 8 falsy values
const falsyValues = [false, 0, -0, 0n, '', null, undefined, NaN];
falsyValues.forEach(val => {
  console.log(`${String(val).padEnd(10)} -> ${Boolean(val)}`);
});

console.log('---');

// Common truthy surprises
const truthySurprises = ['0', 'false', [], {}, function(){}];
truthySurprises.forEach(val => {
  console.log(`${String(val).padEnd(14)} -> ${Boolean(val)}`);
});

// Practical: checking for values
const port = 0;
if (port) console.log('has port');          // skipped! 0 is falsy
if (port !== undefined) console.log('port defined'); // correct

Only 8 values are falsy. Empty arrays, empty objects, and the string '0' are all truthy. Use explicit checks when 0 or '' are valid values.

The + Operator Coercion

// + with strings = concatenation
console.log('5' + 3);       // '53' (number -> string)
console.log(5 + '3');       // '53' (number -> string)
console.log('5' + true);    // '5true'

// + with numbers = addition
console.log(5 + 3);          // 8
console.log(true + true);    // 2 (boolean -> number)
console.log(null + 1);       // 1 (null -> 0)

// Other operators always convert to number
console.log('6' - 1);       // 5 (string -> number)
console.log('6' * '2');      // 12
console.log('abc' - 1);     // NaN

// Explicit conversion
console.log(Number(''));     // 0
console.log(Number('abc'));  // NaN
console.log(Number(true));   // 1
console.log(Number(null));   // 0
console.log(Number(undefined)); // NaN

The + operator prefers string concatenation if either operand is a string. Other math operators (-, *, /) always convert to numbers.

Key points

Concepts covered

Type Coercion, == vs ===, Truthy/Falsy, String Conversion, Number Conversion