"5" + 3 give you "53" but "5" - 3 gives you 2? Why does [] == ![] return true? How does JavaScript decide what type a value should be?
- The difference between implicit and explicit coercion
- How JavaScript converts to strings, numbers, and booleans
- The 8 falsy values every developer must memorize
- How objects convert to primitives
- The famous JavaScript “WAT” moments explained
- Best practices for avoiding coercion bugs
What Is Type Coercion?
Type coercion is the automatic or implicit conversion of values from one data type to another in JavaScript. According to the ECMAScript specification, JavaScript performs these conversions through a set of “abstract operations” — internal algorithms like ToString, ToNumber, and ToBoolean. When you use operators or functions that expect a certain type, JavaScript will convert (coerce) values to make the operation work, sometimes helpfully, sometimes surprisingly. Understanding these conversion rules helps you write predictable, bug-free code.The Shapeshifter Analogy
Imagine JavaScript as an overly helpful translator. When you give it values of different types, it tries to “help” by converting them, sometimes correctly, sometimes… creatively.Explicit vs Implicit Coercion
There are two ways coercion happens:- Explicit Coercion
- Implicit Coercion
Number(), String(), Boolean(), parseInt(), and parseFloat() — give you full control.This is the safe way. You know exactly what’s happening.Why Does JavaScript Do This?
JavaScript is a dynamically typed language. Variables don’t have fixed types. This flexibility means JavaScript needs to figure out what to do when types don’t match.The Three Types of Conversion
Here’s the most important rule: JavaScript can only convert to THREE primitive types:| Target Type | Explicit Method | Common Implicit Triggers |
|---|---|---|
| String | String(value) | + with a string, template literals |
| Number | Number(value) | Math operators (- * / %), comparisons |
| Boolean | Boolean(value) | if, while, !, &&, ||, ? : |
String Conversion
String conversion is the most straightforward. Almost anything can become a string.When Does It Happen?
toString() method and template literals are also common ways to convert values to strings.
String Conversion Rules
| Value | Result | Notes |
|---|---|---|
123 | "123" | Numbers become digit strings |
-12.34 | "-12.34" | Decimals and negatives work too |
true | "true" | Booleans become their word |
false | "false" | |
null | "null" | |
undefined | "undefined" | |
[1, 2, 3] | "1,2,3" | Arrays join with commas |
[] | "" | Empty array becomes empty string |
{} | "[object Object]" | Objects become this (usually useless) |
Symbol("id") | Throws TypeError! | Symbols can’t implicitly convert |
The + Operator’s Split Personality
The+ operator is special: it does both addition and concatenation:
Number Conversion
Number conversion has more triggers than string conversion, and more edge cases to memorize.When Does It Happen?
Number Conversion Rules
| Value | Result | Notes |
|---|---|---|
"123" | 123 | Numeric strings work |
" 123 " | 123 | Whitespace is trimmed |
"123abc" | NaN | Any non-numeric char → NaN |
"" | 0 | Empty string becomes 0 |
" " | 0 | Whitespace-only becomes 0 |
true | 1 | |
false | 0 | |
null | 0 | null → 0 |
undefined | NaN | undefined → NaN (different!) |
[] | 0 | Empty array → "" → 0 |
[1] | 1 | Single element array |
[1, 2] | NaN | Multiple elements → NaN |
{} | NaN | Objects → NaN |
Math Operators Always Convert to Numbers
Unlike+, the other math operators (-, *, /, %) only do math. They always convert to numbers:
The Unary + Trick
The unary+ (plus sign before a value) is a quick way to convert to a number:
Boolean Conversion
Boolean conversion is actually the simplest. Every value is either truthy or falsy.When Does It Happen?
The 8 Falsy Values (Memorize These!)
As documented in MDN’s reference on falsy values, there are 8 common values that convert tofalse. Everything else is true.
document.all. It’s a legacy browser API that returns false in boolean context despite being an object. You’ll rarely encounter it in modern code, but it exists for backwards compatibility with ancient websites.Everything Else Is Truthy!
This includes some surprises:Logical Operators Don’t Return Booleans!
A common misconception:&& and || don’t necessarily return true or false. They return one of the original values:
Object to Primitive Conversion
When JavaScript needs to convert an object to a primitive (including arrays), it follows a specific algorithm.The ToPrimitive Algorithm
Check if already primitive
Determine the 'hint'
- String hint:
String(), template literals, property keys - Number hint:
Number(), math operators, comparisons - Default hint:
+operator,==(usually treated as number)
Try valueOf() or toString()
- For number hint: try
valueOf()first, thentoString() - For string hint: try
toString()first, thenvalueOf()
How Built-in Objects Convert
Custom Conversion with valueOf and toString
You can control how your objects convert:ES6 Symbol.toPrimitive
ES6 introduced a cleaner way to control conversion —Symbol.toPrimitive:
The == Algorithm Explained
The loose equality operator== is where type coercion gets wild. For a deeper dive into all equality operators, see our Equality Operators guide. Here’s how == actually works:
Simplified == Rules
Step-by-Step Examples
Operators & Coercion Cheat Sheet
Quick reference for which operators trigger which coercion:| Operator | Coercion Type | Example | Result |
|---|---|---|---|
+ (with string) | String | "5" + 3 | "53" |
+ (unary) | Number | +"5" | 5 |
- * / % | Number | "5" - 3 | 2 |
++ -- | Number | let x = "5"; x++ | 6 |
> < >= <= | Number | "10" > 5 | true |
== != | Complex | "5" == 5 | true |
=== !== | None | "5" === 5 | false |
&& || | Boolean (internal) | "hi" || "bye" | "hi" |
! | Boolean | !"hello" | false |
if while ? : | Boolean | if ("hello") | true |
& | ^ ~ | Number (32-bit int) | "5" | 0 | 5 |
JavaScript WAT Moments
Let’s explore the famous “weird parts” that make JavaScript… special.1. The + Operator's Split Personality
1. The + Operator's Split Personality
2. Empty Array Weirdness
2. Empty Array Weirdness
3. Boolean Math
3. Boolean Math
4. The Infamous [] == ![]
4. The Infamous [] == ![]
5. "foo" + + "bar"
5. "foo" + + "bar"
6. NaN is Not Equal to Itself
6. NaN is Not Equal to Itself
Number.isNaN() instead of the global isNaN() for reliable NaN checking.7. typeof Quirks
7. typeof Quirks
8. Adding Arrays
8. Adding Arrays
Best Practices
When Implicit Coercion IS Useful
Stack Overflow’s 2023 Developer Survey reports that type-related bugs remain among the most common debugging challenges for JavaScript developers. Despite the gotchas, some implicit coercion patterns are actually helpful:Anti-Patterns to Avoid
Key Takeaways
- Three conversions only — JavaScript converts to String, Number, or Boolean — nothing else
- Implicit vs Explicit — Know when JS converts automatically vs when you control it
-
The 8 common falsy values —
false,0,-0,0n,"",null,undefined,NaN— everything else is truthy (plus the raredocument.all) - + is special — It prefers string concatenation if ANY operand is a string
- - * / % are consistent — They ALWAYS convert to numbers
-
== coerces, === doesn’t — Use
===by default to avoid surprises -
null == undefined — This is true, but neither equals anything else with
== - Objects convert via valueOf() and toString() — Learn these methods to control conversion
-
When in doubt, be explicit — Use
Number(),String(),Boolean() -
NaN is unique — It’s the only value not equal to itself; use
Number.isNaN()to check
Test Your Knowledge
Question 1: What does "5" + 3 return and why?
Question 1: What does "5" + 3 return and why?
"53" (string)The + operator, when one operand is a string, performs string concatenation. The number 3 is converted to "3", resulting in "5" + "3" = "53".Question 2: What are the 8 common falsy values in JavaScript?
Question 2: What are the 8 common falsy values in JavaScript?
false0-00n(BigInt zero)""(empty string)nullundefinedNaN
[], {}, "0", and "false".Bonus: There’s also a 9th falsy value — document.all — a legacy browser API you’ll rarely encounter.Question 3: Why does [] == ![] return true?
Question 3: Why does [] == ![] return true?
![]evaluates first: arrays are truthy, so![]=false- Now we have
[] == false - Boolean converts to number:
[] == 0 - Array converts to primitive:
"" == 0 - String converts to number:
0 == 0 - Result:
true
Question 4: What's the difference between == and === regarding coercion?
Question 4: What's the difference between == and === regarding coercion?
===(strict equality) never coerces. If types differ, it returnsfalseimmediately.==(loose equality) coerces values to the same type before comparing, following a complex algorithm.
=== unless you specifically need coercion.Question 5: What does Number(null) vs Number(undefined) return?
Question 5: What does Number(null) vs Number(undefined) return?
null converts to 0 (like “nothing” = zero), while undefined converts to NaN (like “no value” = not a number).Question 6: Predict the output: true + false + "hello"
Question 6: Predict the output: true + false + "hello"
"1hello"Step by step:true + false=1 + 0=1(booleans → numbers)1 + "hello"="1hello"(number → string for concatenation)
Frequently Asked Questions
What is type coercion in JavaScript?
What is type coercion in JavaScript?
Number(), String(), or Boolean()).What are the falsy values in JavaScript?
What are the falsy values in JavaScript?
false, 0, -0, 0n (BigInt zero), "" (empty string), null, undefined, and NaN. As documented by MDN, every other value in JavaScript is truthy — including empty arrays [], empty objects {}, and the string "0".Why does "5" + 3 return "53" but "5" - 3 returns 2?
Why does "5" + 3 return "53" but "5" - 3 returns 2?
+ operator has a dual role: it performs both addition and string concatenation. When either operand is a string, + concatenates. The - operator only performs subtraction, so it always converts operands to numbers. This asymmetry is one of the most frequently asked JavaScript interview questions according to Stack Overflow surveys.What is the difference between implicit and explicit type coercion?
What is the difference between implicit and explicit type coercion?
Number("42") or String(42). Implicit coercion happens automatically when JavaScript encounters mismatched types in operations — for example, "5" - 3 implicitly converts "5" to the number 5. Most style guides recommend explicit coercion for clarity.How do objects convert to primitives in JavaScript?
How do objects convert to primitives in JavaScript?
Symbol.toPrimitive method first, then falls back to valueOf() and toString(). For number hints, valueOf() is tried first; for string hints, toString() is tried first. Arrays convert via toString(), which is why [1,2,3] + "" produces "1,2,3".