SKU // 104

JavaScript Type Coercion

Type coercion is JavaScript automatically converting a value from one type to another so an operation can go ahead. Instead of throwing an error when types do not match, JavaScript "makes them fit." That is convenient until it guesses differently than you did. This lesson covers the rules, the famous surprises, and how to stay out of trouble.

// Implicit vs Explicit

Coercion is implicit: JavaScript does it for you. Conversion is explicit: you ask for it with Number(), String(), or Boolean() (next lesson). Same two strings, two operators, two completely different results:

console.log("5" + "2");   // + with strings: join
console.log("5" - "2");   // - only does math: convert to numbers
52 3

// String Coercion: +

If either side of + is a string, the other side becomes a string and the two are joined. Other values are converted to text first (arrays with their commas, objects as [object Object]):

console.log("5" + 2);
console.log("1" + null, "1" + undefined);
console.log([1, 2] + [3]);
console.log({} + "x");
52 1null 1undefined 1,23 [object Object]x

Without any strings, + adds, turning true into 1 and null into 0. Two arrays have no numbers, so they are turned into strings anyway:

console.log(1 + true, true + true, 1 + null, 1 + undefined);
console.log(JSON.stringify([] + []));   // two empty strings joined
2 2 1 NaN ""

// Numeric Coercion: - * / % and Unary +

Every other math operator only knows numbers, so it converts both sides to numbers. The unary plus, a + in front of a single value, is a short way to force a number:

console.log("5" - 2, "5" * "2", "10" / "2", "7" % "2");
console.log(+"5", +"", +" ", +"abc");
console.log(+true, +false, +null, +undefined);
console.log(+[], +[5], +[1, 2], +{});
3 10 5 1 5 0 0 NaN 1 0 0 NaN 0 5 NaN NaN
Trap: form input is always a string
Values from a text box are strings, so "5" + "10" is "510", not 15. Convert first: Number(a) + Number(b). The same thing hides in +=: with let s = "5", s += 1 makes "51", while s++ converts and gives the number 6.

// Boolean Coercion: Truthy and Falsy

In an if, a loop condition, !, &&, or ||, any value is coerced to a boolean. There are exactly 8 falsy values; everything else is truthy:

const falsy = [false, 0, -0, 0n, "", null, undefined, NaN];
console.log(falsy.map(v => Boolean(v)));

console.log(Boolean("0"), Boolean("false"), Boolean(" "), Boolean([]), Boolean({}));
[false, false, false, false, false, false, false, false] true true true true true

The second line surprises people: the text "0" and "false" are non-empty strings, so they are truthy, and so is every array and object, even empty ones. The double NOT !!value is a common short way to write Boolean(value).

W3Schools error
Its falsy list is "0, "", null, undefined, NaN, and false": 6 values. It is missing -0 and 0n (BigInt zero), for 8 in total.

// && and || Return a Value, Not a Boolean

console.log(0 || "default", "" || "none");
console.log("hi" && "there", null && "x");
default none there null

|| returns the first truthy value (or the last value), and && returns the first falsy value (or the last value). They coerce only to decide; what you get back is one of the original values.

// Loose Equality: ==

== coerces both sides toward a common type before comparing. The results are hard to predict:

console.log(5 == "5", 0 == "", 0 == "0");
console.log("" == "0");                    // but both equal 0!
console.log(false == "0", [] == false, [0] == false);
console.log(null == 0, null == undefined);
true true true false true true true false true

Look at the first two lines: 0 == "" and 0 == "0", but "" == "0" is false. Two strings are compared as strings, with no conversion. The rules are consistent, but nobody wants to keep them in their head while coding.

Rule
Use === and !==. They never coerce: different types are simply not equal. The one widely accepted use of == is value == null, meaning "null or undefined" (JS undefined).

// Comparisons: < and >

If both sides are strings, they are compared alphabetically, character by character. Otherwise both are converted to numbers:

console.log("10" < "9");    // text: "1" comes before "9"
console.log(10 < "9");      // one number: numeric compare
console.log(null >= 0, null > 0, null == 0);
true false true false false

The last line looks impossible: null is at least 0, but not greater than 0, and not equal to 0. The comparison operators convert null to 0, but == has its own rule that null only equals undefined.

// Where Else Coercion Happens

const o = {};
o[1] = "a";
o["1"] = "b";                  // same key: 1 became "1"
console.log(Object.keys(o), o[1]);

console.log([10, 9, 1, 100].sort());   // sort compares as strings
console.log(`${null} and ${[1, 2]}`);
["1"] b [1, 10, 100, 9] null and 1,2

// Values That Refuse to Coerce

A few types throw instead of guessing, which is actually safer:

console.log(1n + 1);
TypeError: Cannot mix BigInt and other types, use explicit conversions

Symbols also refuse: Symbol("a") + 1 is TypeError: Cannot convert a Symbol value to a number.

// Staying Out of Trouble

Compare with === and !==No hidden conversion
Convert input on purpose: Number(), String()Your intent is visible in the code
Check numbers with Number.isNaN / Number.isFiniteCatches failed conversions
Give sort a compare function for numbersAvoids string ordering
Use ?? for defaults when 0 or "" are valid|| treats them as missing

// Quick Check

What does this log?

console.log("3" - - "3", "b" + "a" + +"a" + "a");
Show answer
6 baNaNa. - "3" is -3, and "3" - -3 is 6. In the second, +"a" is NaN, which gets joined into the string as the text "NaN".

Which of these values is falsy?

  1. "0"
  2. []
  3. 0n
  4. "false"
Show answer
C. 0n (BigInt zero) is one of the 8 falsy values. A and D are non-empty strings, and every array is truthy.

Two text boxes hold "5" and "10", and a + b shows 510. Fix it.

Show answer
Convert before adding: Number(a) + Number(b) (or +a + +b) gives 15.

// Try It

  1. Click Open Playground. Predict, then test, 10 expressions mixing strings, numbers, null, and [] with + and -
  2. Log Boolean() of all 8 falsy values and 5 surprising truthy ones
  3. Find three pairs where a == b is true but a === b is false
  4. Sort [25, 3, 100, 42] with and without a compare function and explain the difference
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:48 AM ET