Technology · JavaScript
IntermediateJavaScript Type Coercion
Understand how JavaScript converts types automatically and avoid common equality and comparison bugs.
TL;DR
- 01Compare values with === to avoid surprise type conversions.
- 02Learn which values count as falsy in conditionals.
- 03Convert types explicitly with Boolean, Number, and String.
Loose vs Strict Equality
- Use
===to compare both value and type with zero implicit conversion.console.log(1 === 1); // true console.log(1 === '1'); // false - Use
==carefully, since it converts operands to a common type before comparing.console.log(1 == '1'); // true console.log(0 == false); // true - Compare
nullandundefinedwith==only when checking for either value at once.function isMissing(value) { return value == null; // true for both null and undefined } - Always prefer
!==over!=for the same reason strict equality beats loose equality.console.log('5' !== 5); // true, different types - NaN never equals anything, even itself, under either equality operator.
console.log(NaN === NaN); // false console.log(Number.isNaN(NaN)); // true
Truthy and Falsy Values
- JavaScript treats every value as either truthy or falsy when used in a boolean context.
if ('hello') { console.log('runs, because non-empty strings are truthy'); } - Memorize the eight falsy values:
false,0,-0,0n,'',null,undefined, andNaN.[false, 0, -0, 0n, '', null, undefined, NaN].forEach(v => console.log(Boolean(v)) // always false ); - Empty arrays and empty objects are truthy, which surprises many developers.
if ([]) console.log('runs'); // [] is truthy if ({}) console.log('runs'); // {} is truthy - Check array length explicitly instead of relying on the array itself being falsy.
const items = []; if (items.length === 0) console.log('empty array'); - Use the double negation trick
!!valueto force a quick conversion to a real boolean.console.log(!!'text'); // true console.log(!!0); // false
Implicit Conversion
- The
+operator concatenates strings when either operand is a string.console.log(1 + '1'); // "11" console.log('a' + 1); // "a1" - Subtraction, multiplication, and division force both operands toward numbers.
console.log('5' - 2); // 3 console.log('5' * '2'); // 10 - Comparing a string and a number with relational operators converts the string to a number first.
console.log('10' > 5); // true - Template literals always convert embedded expressions to strings automatically.
const age = 30; console.log(`Age: ${age}`); // "Age: 30" - Objects convert to primitives using
valueOf()ortoString()during arithmetic or string operations.const obj = { valueOf: () => 42 }; console.log(obj + 1); // 43
Explicit Conversion
- Use
Boolean(value)to convert any value to true or false explicitly.console.log(Boolean('')); // false console.log(Boolean('0')); // true, non-empty string - Use
Number(value)to convert strings or other types into a numeric value.console.log(Number('42')); // 42 console.log(Number('abc')); // NaN - Use
String(value)to convert any value into its string representation.console.log(String(42)); // "42" console.log(String(null)); // "null" - Use
parseInt()orparseFloat()when a string has trailing non-numeric characters.console.log(parseInt('42px', 10)); // 42 console.log(Number('42px')); // NaN - Prefer explicit conversion over relying on implicit coercion, since it documents intent for future readers.
const total = Number(input.value) + 10; // clear and predictable
Common Gotchas
- An empty array loosely equals false because both reduce to 0 during comparison.
console.log([] == false); // true - Adding two arrays together converts both to strings and concatenates them.
console.log([1, 2] + [3, 4]); // "1,23,4" nullandundefinedare loosely equal to each other but to nothing else.console.log(null == undefined); // true console.log(null == 0); // falsetypeof nullfamously returns"object", a long-standing JavaScript quirk.console.log(typeof null); // "object"- Comparing objects, even with identical contents, checks reference equality, not structural equality.
console.log({ a: 1 } === { a: 1 }); // false
Tips
- 01Use strict equality with three equals signs by default so comparisons never silently convert types behind your back.
- 02Convert values explicitly with Number(), String(), or Boolean() so your intent is obvious to anyone reading the code.
- 03Check for NaN with Number.isNaN() instead of equality, since NaN never equals anything, including itself.
Warnings
- 01Loose equality with two equals signs converts types before comparing, which produces confusing results like '0' == false.
- 02Empty arrays and objects are truthy even though they look empty, so don't test them directly in an if statement.
- 03Adding a number and a string triggers string concatenation instead of arithmetic, often producing unexpected text output.
FAQ
- The == operator, called loose equality, converts operands to a matching type before comparing them. The === operator, strict equality, compares both value and type with no conversion. Strict equality is recommended in almost all cases because it avoids unpredictable coercion rules.
- Loose equality coerces both sides toward numbers when comparing an object and a boolean. The empty array converts to an empty string, then to the number 0, and false also converts to 0. Since both sides become 0, the comparison returns true, which is why strict equality avoids this trap.
- The falsy values are false, 0, -0, 0n, empty string, null, undefined, and NaN. Every other value, including empty arrays, empty objects, and the string "0", is truthy. Knowing this list prevents bugs in conditionals that assume emptiness means false.
- When either operand of the + operator is a string, JavaScript converts the other operand to a string too. This triggers concatenation instead of addition. Use the minus or multiplication operators, or Number() conversion, to force numeric math instead.
- Both == and === compare objects by reference, not by their contents. Two separate objects with identical properties are never equal under either operator. Compare specific properties individually, or use a deep-equality helper like lodash's isEqual for structural comparison.