ESC

Type to search the knowledge base.

Type Coercion Rules

Predict JS coercion: ToPrimitive, == abstract equality, + vs concat, truthiness, and how to avoid the worst comparisons.

intermediate3 min read
  • javascript
  • type-coercion

JS is dynamically typed and will coerce values in operators and conditionals. You don’t need every corner of the abstract equality algorithm memorized — you need the patterns that show up in bugs and interviews, and the habit of using === + explicit conversion.

Explicit conversion (prefer)

Number('42');     // 42
Number('');       // 0
Number('  ');     // 0
Number('1px');    // NaN
parseInt('1px', 10); // 1
String(42);       // '42'
Boolean(0);       // false

+value as unary number cast is common; '' + value stringifies.

The + operator special case

1 + 2;       // 3
'1' + 2;     // '12' — if either side is string, concat
1 + '2';     // '12'
1 + true;    // 2 — true → 1
1 + null;    // 1 — null → 0
1 + undefined; // NaN

Subtraction always goes numeric:

'6' - 1; // 5
'6' + 1; // '61'

== vs ===

0 == false;      // true
'' == false;     // true
null == undefined; // true
null == 0;       // false
'0' == 0;        // true
[] == false;     // true  (array → '' → 0)
[] == ![];       // true  — meme, but real

Always use === / !== unless you deliberately want == null for nullish check.

ToPrimitive sketch

Objects become primitives via Symbol.toPrimitive, then valueOf / toString depending on hint (number vs string).

const obj = {
  valueOf() { return 3; },
  toString() { return 'x'; },
};
obj + 1; // 4 — prefers valueOf for numeric +
String(obj); // 'x' if valueOf not used for string hint

Dates prefer toString for many coercions — classic interview trivia.

Comparisons with < / >

'10' > '9'; // false — lexicographic strings
'10' > 9;   // true  — numeric coercion

Convert first when comparing user input numbers.

Truthy coercion in && / ||

Covered in truthy/falsy notes; remember operators return operand values, not always boolean.

const name = inputName || 'Guest';
// wrong if inputName can be ''

Practical rules for production

  1. === for equality
  2. Number.parseInt(s, 10) / Number with Number.isFinite for numbers
  3. ?? for nullish defaults
  4. Avoid == with arrays/objects
  5. Sanitize API payloads at the boundary so UI code sees real types
function asInt(v, fallback = 0) {
  const n = typeof v === 'number' ? v : Number.parseInt(String(v), 10);
  return Number.isFinite(n) ? n : fallback;
}

Interview answer (out loud)

“Coercion happens in operators and boolean contexts. + concatenates if either side is string; - always numeric. == applies abstract equality with many surprises, so I use ===. I convert explicitly at boundaries and use ?? instead of || when zero or empty string is valid.”

Further reading

Related guides