JavaScript Roadmap — Day 6: Type Conversion and Coercion

 

JavaScript · Day 6 of 180 · Beginner Phase

Type Conversion and Coercion

JavaScript secretly changes your data types behind your back. This is called coercion — and it is responsible for some of the most confusing bugs beginners ever face.

Day 6 / 180
Beginner Phase

Look at this code carefully and predict what it will print before reading the answers:

JavaScript — Can you predict the output?
// What does each line print?
console.log("5" + 3);
console.log("5" - 3);
console.log(true + 1);
console.log(false + 1);
console.log("" + 5);
console.log("5" * "3");

Answers:

"53" — string + number = string concatenation
2 — string - number = number subtraction
2 — true converts to 1
1 — false converts to 0
"5" — empty string + number = string
15 — both strings convert to numbers for multiplication

If any of those surprised you — this lesson is exactly what you need. JavaScript is doing something called type coercion — silently converting your data from one type to another without telling you. Understanding this completely removes an entire category of bugs from your code forever.

1. Explicit vs Implicit — You vs JavaScript

There are two ways a type changes in JavaScript. Either you deliberately convert it — or JavaScript secretly converts it for you:

Type Who does it Example Safe?
Explicit Conversion You — intentionally Number("5") ✅ Predictable
Implicit Coercion JavaScript — secretly "5" - 3 ⚠️ Unpredictable

2. Explicit Conversion — You Are in Control

JavaScript gives you built-in functions to convert types manually. These are predictable, safe, and always do exactly what you expect. Every professional JavaScript developer uses these daily:

JavaScript — Converting to Number
// Three ways to convert to Number
Number("42")       // 42
Number("3.14")     // 3.14
Number("")         // 0  ← empty string becomes 0
Number("hello")    // NaN ← cannot convert text
Number(true)       // 1
Number(false)      // 0
Number(null)       // 0
Number(undefined)  // NaN

// parseInt and parseFloat — for strings with mixed content
parseInt("42px")      // 42  ← stops at non-number
parseInt("3.9")       // 3   ← cuts decimal part
parseFloat("3.9em")   // 3.9 ← keeps decimal
parseInt("hello")     // NaN ← no number to find

// Unary + operator — shortest way to convert
+"42"     // 42
+true     // 1
+false    // 0
+""       // 0
JavaScript — Converting to String
// Convert anything to String
String(42)          // "42"
String(3.14)        // "3.14"
String(true)        // "true"
String(false)       // "false"
String(null)        // "null"
String(undefined)   // "undefined"

// .toString() method — same result
(42).toString()      // "42"
(true).toString()    // "true"

// toString with base — converts to different number systems
(255).toString(16)   // "ff"  (hexadecimal)
(8).toString(2)     // "1000" (binary)
(8).toString(8)     // "10"   (octal)
JavaScript — Converting to Boolean
// The 6 FALSY values — these all become false
Boolean(false)      // false
Boolean(0)          // false
Boolean("")         // false (empty string)
Boolean(null)       // false
Boolean(undefined)  // false
Boolean(NaN)        // false

// EVERYTHING else is truthy
Boolean(1)          // true
Boolean("hello")    // true
Boolean([])         // true ← empty array is TRUTHY!
Boolean({})         // true ← empty object is TRUTHY!
Boolean("0")        // true ← "0" as STRING is TRUTHY!
Boolean("false")    // true ← "false" as STRING is TRUTHY!

// Short way using !! (double NOT)
!!0          // false
!!"hello"    // true
!!null       // false
!![]         // true

3. Implicit Coercion — JavaScript's Secret Decisions 🔥

This is where JavaScript gets wild. When you use operators like +, -, *, /, or comparisons like ==, JavaScript has to decide what type to convert things to. Its decisions are not always obvious. Let us go through every rule:

The + Operator — The Sneaky One

The + operator has a split personality. It does addition for numbers but concatenation for strings. And when it sees a mix — it always chooses string concatenation. This surprises everyone at first:

JavaScript — The + Operator trap
// Number + Number = addition (expected)
1 + 2           // 3

// String + String = concatenation (expected)
"hello" + " world"  // "hello world"

// String + Number = STRING wins, concatenates
"5" + 3         // "53"  NOT 8!
3 + "5"         // "35"  order does not matter
"" + 42         // "42"  number becomes string

// The chain problem — left to right evaluation
1 + 2 + "3"     // "33"  (1+2=3, then 3+"3"="33")
"1" + 2 + 3     // "123" ("1"+2="12", then "12"+3="123")

// Boolean + Number
true + 1        // 2  (true = 1)
false + 1       // 1  (false = 0)
true + true     // 2

// null and undefined
null + 1        // 1  (null = 0)
undefined + 1   // NaN

Other Operators — Number Always Wins

For -, *, /, and % there is no string version. So JavaScript always tries to convert everything to a number. This is why "5" - 3 gives 2 but "5" + 3 gives "53":

JavaScript — - * / always convert to Number
// Subtraction — string converts to number
"10" - 3        // 7
"10" - "3"      // 7

// Multiplication
"5" * "3"       // 15
"5" * true      // 5  (true = 1)
"5" * false     // 0  (false = 0)
"5" * null      // 0  (null = 0)
"5" * undefined // NaN
"hello" * 2    // NaN (cannot convert "hello")

// Division
"10" / "2"      // 5
true / false    // Infinity (1 / 0)

4. The == Operator — The Most Dangerous Coercion 🔥

Loose equality == converts types before comparing. This leads to results that look completely insane until you understand the rules. Study these carefully — they appear in every JavaScript interview:

JavaScript — == loose equality surprises
0 == false        // true  (false → 0)
1 == true         // true  (true → 1)
"" == false       // true  (both → 0)
"0" == false      // true  ("0" → 0, false → 0)
"1" == true       // true  ("1" → 1, true → 1)
"" == 0           // true  ("" → 0)
"5" == 5          // true  ("5" → 5)

// These look false but are true — brain benders
[] == false        // true  ([] → "" → 0, false → 0)
[] == 0           // true  ([] → "" → 0)
[] == ""          // true  ([] → "")
[1] == 1         // true  ([1] → "1" → 1)

// The fix — always use === (strict equality)
0 === false       // false ✅ different types
"" === 0          // false ✅ different types
"5" === 5         // false ✅ different types

🔥 The rule that saves everything: Always use === instead of == in your code. The only exception is checking for null and undefined together with value == null — which is actually a clean, readable pattern that senior developers use intentionally.

Pro Tip #1 — Always validate before converting
When converting user input to a number always check if the result is NaN using isNaN() or Number.isNaN() afterward. User input like "abc" or an empty field will produce NaN silently and then every calculation involving it will also be NaN. Always validate first.
Pro Tip #2 — parseInt needs a radix argument
Always pass the base as a second argument to parseInt. Write parseInt("10", 10) not just parseInt("10"). Without the radix, older browsers could interpret strings starting with "0" as octal (base 8). It is a small habit that prevents a real bug.
Pro Tip #3 — Empty array [] is truthy but == false
Boolean([]) is true — empty array is truthy. But [] == false is also true. How can something be truthy AND equal to false? Because == does not use Boolean conversion — it converts both sides to numbers first. This is one of the most confusing JavaScript quirks and a common interview trick question.

Quick Reference — Conversion Rules

Value → Number → String → Boolean
0 0 "0" ❌ false
1 1 "1" ✅ true
"" 0 "" ❌ false
"0" 0 "0" ✅ true
"hello" NaN "hello" ✅ true
true 1 "true" ✅ true
false 0 "false" ❌ false
null 0 "null" ❌ false
undefined NaN "undefined" ❌ false
[] 0 "" ✅ true

Try It Yourself

Run the code and study every output. Then try changing the operators and values to test your understanding.

✏️ Try it Yourself — Type Coercion
OUTPUT
// Click Run Code to see output
💡 Edit code then click run!

Practice Tasks

Task 1 — Easy: Predict Before Running

Before running the code — write your predicted output in comments next to each line. Then run it and see how many you got right. Do this for: "10" + 5, "10" - 5, true + true + true, null + undefined, "5" * false.

Task 2 — Medium: Safe Input Converter

Write a function safeToNumber(value) that converts any input to a number. If the result is NaN it should return 0 as a fallback. Test it with: "42", "hello", true, null, undefined, "".

Task 3 — Hard: The Coercion Detective

These expressions all return true with ==. For each one — explain in a comment exactly why JavaScript considers them equal and what conversions happened: [] == false, "" == 0, [1] == 1, null == undefined. Then rewrite each using === and explain why they now return false.

Next Lesson
Day 7 — Arithmetic Operators
Read Next Lesson →
Want daily web dev tips?
Follow Muhammad Waheed Asghar for daily JavaScript and CSS tips!