Type Coercion Rules
Predict JS coercion: ToPrimitive, == abstract equality, + vs concat, truthiness, and how to avoid the worst comparisons.
- 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
===for equalityNumber.parseInt(s, 10)/NumberwithNumber.isFinitefor numbers??for nullish defaults- Avoid
==with arrays/objects - 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
- Type conversion — javascript.info
- Equality comparisons — MDN
- Abstract Equality Comparison — ECMA-262
Related
Related guides
- AbortControllerCancel fetch and other async work with AbortController and AbortSignal — timeouts, race conditions, and cleanup when components unmount.
- Array find, some, every, includesShort-circuiting array predicates: find, findIndex, some, every, and includes — when to use each and common interview traps.
- Array map, filter, reducemap, filter, and reduce as the core transform toolkit — immutability, chaining costs, reduce patterns, and when a plain loop is clearer.
- Arrow Functions Deep DiveLexical this, no arguments object, no construct, concise bodies — when arrows help and when methods and generators need classic functions.
- Async Iteration and for await...ofAsync iterables, for await...of, and streaming data — how async iterators differ from Promise.all and when to use each.