Follow AiTechWorlds on LinkedIn for professional AI content!Follow Now →
18 minLesson 3 of 35
JavaScript Fundamentals

Data Types & Type Coercion


title: "Data Types & Type Coercion" description: "Understand JavaScript's 8 data types, the quirks of implicit coercion, how == and === differ, and how to convert types safely and predictably." duration: "40 min" difficulty: "beginner" order: 3

Data Types & Type Coercion

JavaScript is a dynamically typed language. A variable has no fixed type — it holds whatever value you assign to it. Understanding how JavaScript categorizes and converts values is essential for avoiding the category of bugs that trips up beginners and even experienced developers.

The 8 Data Types

JavaScript has 7 primitive types and 1 object type.

Primitive Types

Primitives are immutable values. When you work with them, you work with the value directly — not a reference.

// 1. String — text, always in quotes (single, double, or backtick)
const name = "Alice";
const greeting = 'Hello';
const message = `Hi, ${name}`; // template literal — more on this below

// 2. Number — integers and decimals share one type
const age = 30;
const price = 9.99;
const negative = -42;
const scientific = 1.5e6; // 1500000

// 3. BigInt — integers too large for Number (> 2^53 - 1)
const bigNumber = 9007199254740991n; // note the 'n' suffix

// 4. Boolean — only two values
const isActive = true;
const isDeleted = false;

// 5. undefined — a variable declared but not assigned
let score;
console.log(score); // undefined

// 6. null — an intentional absence of value (you set this explicitly)
const selectedUser = null;

// 7. Symbol — a unique, immutable identifier (advanced, used for object keys)
const id = Symbol("id");

The Object Type

Everything that is not a primitive is an object. This includes plain objects, arrays, functions, dates, and regular expressions.

const user = { name: "Alice", age: 30 };  // object
const scores = [98, 87, 92];              // array (a special object)
function greet() {}                        // function (also a special object)

The typeof Operator

typeof returns a string describing the type of a value.

typeof "hello"     // "string"
typeof 42          // "number"
typeof 9n          // "bigint"
typeof true        // "boolean"
typeof undefined   // "undefined"
typeof Symbol()    // "symbol"
typeof {}          // "object"
typeof []          // "object"  (arrays are objects)
typeof function(){}// "function"

The typeof null Bug

typeof null // "object"

This is a well-known bug in JavaScript that has existed since the language was created in 1995. It cannot be fixed without breaking existing code on the web. null is a primitive — it is not an object. When checking for null, use strict equality:

const value = null;
console.log(value === null); // true  — correct way to check for null
console.log(typeof value === "object"); // true — misleading, don't rely on this

Implicit Type Coercion

JavaScript automatically converts types when operators are used with mismatched types. This is called implicit coercion, and it is the source of JavaScript's most infamous quirks.

The + Operator: Addition vs Concatenation

+ either adds numbers or concatenates strings. If either operand is a string, both are treated as strings.

"5" + 3      // "53"  — 3 is coerced to a string
"5" + true   // "5true"
1 + 2 + "3"  // "33"  — left to right: 1+2=3, then 3+"3"="33"
"3" + 1 + 2  // "312" — left to right: "3"+1="31", then "31"+2="312"

Arithmetic Operators: String to Number

All other arithmetic operators (-, *, /, %) coerce strings to numbers:

"5" - 3     // 2
"5" * 2     // 10
"5" - true  // 4  (true coerces to 1)
"5" - false // 5  (false coerces to 0)
"5" - null  // 5  (null coerces to 0)

The Famous Weird Table

These are real JavaScript expressions you can run in any browser console:

[] + []    // ""      — two arrays coerce to empty strings, concatenated
[] + {}    // "[object Object]"
{} + []    // 0       — {} is parsed as an empty block, not an object; +[] is 0
true + true           // 2
true + false          // 1
[] == false           // true
null == undefined     // true
null == false         // false  (null only loosely equals undefined)
NaN == NaN            // false  (NaN is not equal to anything, including itself)

These results exist because of coercion rules, and they are why professional JavaScript relies on strict equality.

== vs ===

  • == (loose equality) — coerces types before comparing
  • === (strict equality) — compares value and type, no coercion
0 == false    // true  — false coerces to 0
0 === false   // false — different types

"" == false   // true
"" === false  // false

null == undefined  // true
null === undefined // false

1 == "1"  // true
1 === "1" // false

Always use === in professional code. The only legitimate use of == is checking for null and undefined simultaneously: value == null catches both.

NaN: Not a Number

NaN is a number type value that represents an invalid numeric operation.

typeof NaN  // "number"  — confusingly, NaN is of type number

"hello" * 2    // NaN
parseInt("abc") // NaN
0 / 0           // NaN

NaN is the only value in JavaScript that is not equal to itself. Use Number.isNaN() to check for it:

NaN === NaN           // false
isNaN("hello")        // true  — misleading: converts to number first, then checks
Number.isNaN("hello") // false — correct: only true if value is actually NaN
Number.isNaN(NaN)     // true

Prefer Number.isNaN() over the global isNaN().

Explicit Type Conversion

When you need to convert types, do it explicitly so the intent is clear.

// To Number
Number("42")      // 42
Number("3.14")    // 3.14
Number("")        // 0
Number("hello")   // NaN
Number(true)      // 1
Number(false)     // 0
Number(null)      // 0
Number(undefined) // NaN

parseInt("42px")   // 42  — parses leading integer from a string
parseFloat("3.5kg") // 3.5

// To String
String(42)       // "42"
String(true)     // "true"
String(null)     // "null"
String(undefined)// "undefined"
(42).toString()  // "42"

// To Boolean
Boolean(0)         // false
Boolean("")        // false
Boolean(null)      // false
Boolean(undefined) // false
Boolean(NaN)       // false
Boolean(false)     // false
// Everything else is true:
Boolean(1)         // true
Boolean("hello")   // true
Boolean([])        // true  — empty array is truthy!
Boolean({})        // true  — empty object is truthy!

Truthy and Falsy Values

In a boolean context (like an if condition), every value in JavaScript is either truthy or falsy.

The 6 falsy values:

false, 0, "", null, undefined, NaN

Every other value is truthy, including "0", [], and {}.

if ("") {
  console.log("falsy — this won't run");
}

if ("hello") {
  console.log("truthy — this runs"); // "truthy — this runs"
}

if ([]) {
  console.log("empty array is truthy — this runs"); // runs
}

This is used in practice to check whether a value exists before using it:

const username = getUserInput(); // might return "" or a name

if (username) {
  console.log(`Welcome, ${username}`);
} else {
  console.log("Please enter a username");
}

Template Literals

Template literals (backtick strings) allow embedded expressions and multi-line strings without concatenation:

const product = "keyboard";
const price = 79.99;

// Old way — hard to read
const msg1 = "The " + product + " costs $" + price;

// Template literal — clean and readable
const msg2 = `The ${product} costs $${price}`;

console.log(msg2); // "The keyboard costs $79.99"

// Multi-line
const html = `
  <div class="card">
    <h2>${product}</h2>
    <p>$${price}</p>
  </div>
`;

Any valid JavaScript expression can go inside ${}:

const a = 10;
const b = 5;
console.log(`${a} + ${b} = ${a + b}`);         // "10 + 5 = 15"
console.log(`${a > b ? "greater" : "lesser"}`); // "greater"

Key Takeaways

  • JavaScript has 7 primitive types and 1 object type. Primitives are values; objects are references.
  • typeof null returns "object" — this is a known bug. Use === null to check for null.
  • Implicit coercion with + concatenates if any operand is a string; other operators convert to numbers.
  • Always use === for comparisons. Avoid == except for the value == null pattern.
  • Use Number.isNaN() not isNaN().
  • The 6 falsy values are: false, 0, "", null, undefined, NaN. Everything else is truthy.
  • Use template literals for string construction — they are cleaner and more readable.
📱

Get this course's notes on Telegram!

Free cheat sheets, summaries & practice exercises

Get Notes Free →
!