Free lesson · JavaScript Basic to Advance
Type Coercion: Implicit and Explicit
What Is Type Coercion?
Type coercion is JavaScript automatically converting a value from one type to another when an operation expects a different type than what you gave it. It happens silently, constantly, and is the source of more JavaScript confusion than any other single feature.
console.log("5" - 3); // 2 — the string "5" got coerced to a number
console.log("5" + 3); // "53" — but here the number 3 got coerced to a string
console.log(true + 1); // 2 — true got coerced to 1
console.log([] + []); // "" — both arrays got coerced to empty strings
console.log([] + {}); // "[object Object]" — yes, really
console.log(null + 1); // 1 — null got coerced to 0
console.log(undefined + 1); // NaN — undefined got coerced to NaN
Every one of those produces a result through silent type conversion. The rules behind each are specific, learnable, and — once you understand them — perfectly logical. Until you understand them, JavaScript will keep surprising you.
This is the longest, densest Topic in Module 2 because type coercion is the single concept that separates JavaScript intermediates from JavaScript beginners.
Why Coercion Exists
Go back to Module 1. JavaScript was designed in ten days. One of Brendan Eich's choices was to make the language "forgiving" — if you tried to add a string and a number, the language wouldn't throw an error. It would just figure out something to do.
This made JavaScript easy for beginners to start writing. It also locked in a set of behaviors that, decades later, every JavaScript developer has to memorize because changing them would break the web. Type coercion is JavaScript's most powerful and most dangerous feature, and it exists because of decisions that couldn't be undone after the language shipped.
Two Kinds of Coercion
Coercion happens in two places:
Implicit coercion — JavaScript does it automatically when you use operators on mismatched types. This is the surprising kind, and the one this Topic focuses on.
Explicit coercion — you ask for it on purpose using functions like Number(), String(), Boolean(). This is the safe kind, because you can see it happening.
// Implicit (silent, automatic)
console.log("10" * 2); // 20
console.log("10" + 2); // "102"
// Explicit (deliberate, visible)
console.log(Number("10") * 2); // 20
console.log(String(10) + "2"); // "102"
The results are the same. The difference is readability. When someone reads your code six months from now, explicit coercion makes the intent obvious. Implicit coercion makes them wonder if you knew what you were doing.
The Three Coercion Targets
JavaScript coerces values toward one of three target types depending on the operation:
graph TD
A[Value used in context] --> B{What does the<br/>operation expect?}
B -->|Arithmetic operators<br/>except plus| C[Coerce to Number]
B -->|Plus operator with<br/>a string operand| D[Coerce to String]
B -->|if statement, loops,<br/>logical operators| E[Coerce to Boolean]
style C fill:#7c3aed,color:#fff
style D fill:#7c3aed,color:#fff
style E fill:#7c3aed,color:#fff
This diagram shows the three targets JavaScript coerces values toward. When the operation is arithmetic except for the plus operator, the value is coerced to a number. When the plus operator has a string on either side, the other value is coerced to a string. When the value is used in a boolean context like an if statement or a logical operator, it's coerced to a boolean.
Let me walk through each target with the rules.
Coercion to Number
When JavaScript needs a number (for -, *, /, %, **, comparison operators like > and <), it coerces other types using these rules:
console.log(Number("42")); // 42
console.log(Number("3.14")); // 3.14
console.log(Number("")); // 0 — empty string becomes 0
console.log(Number(" ")); // 0 — whitespace-only string becomes 0
console.log(Number("hello")); // NaN — non-numeric strings become NaN
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0 — null becomes 0
console.log(Number(undefined)); // NaN — undefined becomes NaN
console.log(Number([])); // 0 — empty array becomes 0
console.log(Number([42])); // 42 — single-element array becomes that element
console.log(Number([1, 2])); // NaN — multi-element array becomes NaN
console.log(Number({})); // NaN — objects become NaN
The pattern: numeric-looking strings convert cleanly, true/false become 1/0, null becomes 0, undefined becomes NaN. Arrays and objects have weird rules that exist primarily so you remember not to do arithmetic with them.
Interactive animation: Number() and parseInt() run on the same inputs - they are not interchangeable.
Coercion to String
When you use + with a string, or when JavaScript needs a string (like when concatenating or building template literals), other types coerce using these rules:
console.log(String(42)); // "42"
console.log(String(3.14)); // "3.14"
console.log(String(true)); // "true"
console.log(String(false)); // "false"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
console.log(String([])); // "" — empty string!
console.log(String([1, 2, 3])); // "1,2,3" — comma-separated
console.log(String({})); // "[object Object]"
These rules are more predictable than numeric coercion. Primitives convert to their text representation. Arrays join their elements with commas. Objects produce the dreaded "[object Object]" (a string almost every JavaScript developer has accidentally seen in their UI at some point).
Coercion to Boolean
When JavaScript needs a boolean (inside if, with && and ||, with !), it uses the truthy/falsy rules from Topic 2.4. To remind you:
- Falsy values:
false,0,"",null,undefined,NaN - Truthy values: everything else, including
[],{},"0","false", negative numbers
console.log(Boolean("")); // false
console.log(Boolean("hello")); // true
console.log(Boolean(0)); // false
console.log(Boolean(42)); // true
console.log(Boolean(null)); // false
console.log(Boolean([])); // true — surprises everyone
console.log(Boolean({})); // true
The Plus Operator: The Weirdest Case
The + operator is uniquely confusing because it does two completely different things depending on its operands. Every other arithmetic operator coerces toward numbers. The + operator coerces toward strings if either side is a string.
// All other arithmetic operators coerce to number
console.log("10" - 2); // 8 (number subtraction)
console.log("10" * 2); // 20 (number multiplication)
console.log("10" / 2); // 5 (number division)
console.log("10" % 3); // 1 (number modulo)
// The plus operator: if EITHER side is a string, do string concatenation
console.log("10" + 2); // "102" (string concatenation)
console.log(10 + "2"); // "102" (string concatenation)
console.log(10 + 2 + "3"); // "123" (10+2=12 first, then 12+"3" concatenates)
console.log("1" + 2 + 3); // "123" ("1"+2 concatenates to "12", then +3 concatenates to "123")
The last two examples are evaluated left-to-right. 10 + 2 + "3" adds first (getting 12), then concatenates. "1" + 2 + 3 concatenates first (getting "12"), then concatenates again. The presence of a string anywhere in the expression doesn't immediately make everything a string — it propagates from where the string first appears.
This is exactly the kind of thing interviewers love to ask about.
Interactive animation: Which rule fired, row by row - plus joins when it sees a string, minus and times always want numbers.
The Famous Weird Examples
These are the type coercion examples that get passed around as JavaScript jokes. Each one has a perfectly logical explanation under the rules above.
console.log([] + []); // ""
console.log([] + {}); // "[object Object]"
console.log({} + []); // depends on parsing context (often 0 in REPL, "[object Object]" elsewhere)
console.log(true + true); // 2 (true becomes 1, 1+1=2)
console.log(true + "true"); // "truetrue" (true becomes "true")
console.log(null + 1); // 1 (null becomes 0)
console.log(undefined + 1); // NaN (undefined becomes NaN)
console.log(null + undefined); // NaN
console.log([1] + [2]); // "12" (arrays become strings "1" and "2", then concatenate)
console.log([1] - [2]); // -1 (arrays become numbers 1 and 2, then subtract)
None of these are random. Trace each one through the coercion rules and the answer becomes inevitable. The "JavaScript is broken" jokes about these examples are unfair — the rules are consistent, just unusual.
Interactive animation: [] + {} taken apart in four steps - both sides become strings, then the plus joins them.
Why This Matters in Interviews
Interview: Type coercion is one of the most-asked categories in JavaScript interviews. Common forms:
- Output prediction questions: "What does
[] + []produce?" "What does"5" - 3 + "1"produce?"- Conceptual questions: "Explain the difference between
==and===." "Why does0.1 + 0.2 !== 0.3?"- Best-practices questions: "When should you use implicit coercion?" The correct answer is almost never — prefer explicit
Number(),String(),Boolean()calls for clarity.The next Topic (2.7) covers equality specifically, and Topic 2.8 — Interview Lens: Type Coercion Questions — walks through the full pattern of how these questions are asked, the wrong answers candidates give, and how to structure your response under interview pressure.
Common Pitfalls
Interactive animation: Explicit beats clever - Number(input) and String(count) on one side, the implicit tricks on the other.
Warning: Three rules to live by with coercion.
Prefer explicit coercion in production code.
Number(value)andString(value)make your intent visible. Implicit coercion makes code reviewers (and your future self) work harder to understand what you meant.The
+operator is the trickiest. If either side is a string, you get string concatenation. If neither side is a string, you get numeric addition. Most coercion bugs in real code involve+.Avoid
==for anything other thanvalue == null. The loose equality operator triggers coercion in ways that are hard to predict. Always use===(strict equality) unless you have a specific reason not to. We cover this in detail in the next Topic.
Try It
Exercise: Predict the output of each expression. Then run them to check. Write down which ones surprised you.
"5" + 3 "5" - 3 "5" * "3" 5 + true 5 + "true" 1 + null 1 + undefined [1] + [2] [1] - [2] "10" == 10 "10" === 10For every result that surprised you: walk through which coercion rule was applied. If you can trace each surprise back to a specific rule, you've internalized type coercion. If some still feel random, re-read the section that covers them.