Data Types

โ–ถ Try It Yourself

JavaScript has eight data types โ€” seven primitive types and one complex type (object). Understanding types is fundamental to JavaScript because the language is dynamically typed โ€” variables can hold any type, and types can change at runtime. This flexibility is powerful but also a source of bugs if you do not understand how JavaScript handles types behind the scenes. In this lesson you will learn all eight types and how to detect and work with them reliably.

The Eight JavaScript Data Types

Type Category Example Values
string Primitive 'hello', "world", `template`
number Primitive 42, 3.14, -7, Infinity, NaN
bigint Primitive 9007199254740991n โ€” integers beyond Number limit
boolean Primitive true, false
undefined Primitive undefined โ€” declared but not yet assigned
null Primitive null โ€” intentional absence of a value
symbol Primitive Symbol('id') โ€” unique, immutable identifier
object Complex { name: 'Alice' }, [1,2,3], new Date(), null*

Checking Types with typeof

Expression typeof Result Notes
typeof 'hello' 'string'
typeof 42 'number' Also: NaN, Infinity
typeof true 'boolean'
typeof undefined 'undefined'
typeof null 'object' โš ๏ธ Historic bug โ€” null is NOT an object
typeof {} 'object' Use Array.isArray() to distinguish arrays
typeof [] 'object' Arrays are objects โ€” use Array.isArray()
typeof function(){} 'function' Functions are objects but get their own typeof

Truthy and Falsy Values

Falsy (evaluates to false) Truthy (evaluates to true)
false Everything not on the falsy list
0, -0, 0n 1, -1, any non-zero number
'', "", `` (empty string) 'hello', ' ' (space is truthy!)
null [] empty array โ€” truthy!
undefined {} empty object โ€” truthy!
NaN '0' string zero โ€” truthy!
Note: typeof null === 'object' is one of JavaScript’s most famous bugs โ€” introduced in 1995 and never fixed because fixing it would break the entire internet. To correctly check for null, always use strict equality: value === null. Never use typeof value === 'null' โ€” that will always be false.
Tip: The difference between null and undefined: undefined means a variable was declared but never assigned a value โ€” it is the JavaScript runtime saying “there is nothing here yet.” null is an intentional value you assign to mean “empty” or “no value” โ€” it is the programmer saying “I deliberately set this to nothing.” Use null to clear a value; never assign undefined manually.
Warning: Empty arrays ([]) and empty objects ({}) are truthy โ€” they have a value, just an empty one. This surprises many beginners: if ([]) { console.log('runs!') } will log “runs!” To check if an array is empty, check arr.length === 0. To check if an object has no keys, use Object.keys(obj).length === 0.

Basic Example

// โ”€โ”€ The 7 primitive types โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const greeting   = 'Hello, World!';     // string
const age        = 28;                  // number
const price      = 9.99;               // number (no separate float type)
const isActive   = true;               // boolean
const nothing    = null;               // null
let   notDefined;                      // undefined (no assignment)
const bigNum     = 9007199254740992n;  // bigint (note the n suffix)
const uid        = Symbol('userId');   // symbol โ€” always unique

// โ”€โ”€ typeof detection โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
console.log(typeof greeting);    // 'string'
console.log(typeof age);         // 'number'
console.log(typeof isActive);    // 'boolean'
console.log(typeof nothing);     // 'object' โ† the famous bug (it IS null)
console.log(typeof notDefined);  // 'undefined'
console.log(typeof bigNum);      // 'bigint'
console.log(typeof uid);         // 'symbol'
console.log(typeof {});          // 'object'
console.log(typeof []);          // 'object' โ€” use Array.isArray()

// Correct null check
console.log(nothing === null);    // true โœ…
console.log(Array.isArray([]));   // true โœ…

// โ”€โ”€ Special number values โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
console.log(1 / 0);              // Infinity
console.log(-1 / 0);             // -Infinity
console.log(0 / 0);              // NaN
console.log(Number.isNaN(0/0));  // true โ€” use Number.isNaN(), not isNaN()

// โ”€โ”€ Truthy / falsy in action โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const values = [0, '', null, undefined, NaN, false, [], {}, 'hello', 42];
values.forEach(v => {
  console.log(`${String(v).padEnd(10)} โ†’ ${v ? 'truthy' : 'falsy'}`);
});
// 0          โ†’ falsy
// ''         โ†’ falsy
// null       โ†’ falsy
// undefined  โ†’ falsy
// NaN        โ†’ falsy
// false      โ†’ falsy
// []         โ†’ truthy   โ† surprises beginners!
// {}         โ†’ truthy   โ† surprises beginners!
// hello      โ†’ truthy
// 42         โ†’ truthy

// โ”€โ”€ Dynamic typing โ€” types can change โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
let dynamic = 42;
console.log(typeof dynamic);  // 'number'
dynamic = 'now a string';
console.log(typeof dynamic);  // 'string'
dynamic = { key: 'value' };
console.log(typeof dynamic);  // 'object'

How It Works

Step 1 โ€” Primitives Are Stored by Value

When you assign a primitive to a variable, the actual value is stored directly in the variable. Copying a primitive copies the value: let b = a creates a completely independent copy. Changing b has no effect on a.

Step 2 โ€” Objects Are Stored by Reference

Objects (including arrays and functions) are stored by reference โ€” the variable holds a pointer to the location in memory where the object lives. Copying an object variable copies the reference, not the object. Two variables pointing to the same object means changing one changes the other.

Step 3 โ€” NaN Is a Number Type

NaN stands for “Not a Number” โ€” but typeof NaN is 'number'. It is the result of invalid arithmetic: 0/0, parseInt('hello'), Math.sqrt(-1). NaN is the only value in JavaScript not equal to itself: NaN === NaN is false. Always use Number.isNaN() to check for it.

Step 4 โ€” JavaScript Is Dynamically Typed

Unlike Java or TypeScript, JavaScript does not enforce types on variables. A variable can hold a string, then a number, then an object โ€” the type is determined at runtime by whatever value is currently stored. This is convenient but requires careful attention to avoid type-related bugs.

Step 5 โ€” Falsy Values Are the Six Exceptions

In a boolean context (like an if condition), JavaScript converts any value to true or false. Only six values are falsy: false, 0, '', null, undefined, and NaN. Everything else โ€” including empty arrays and empty objects โ€” is truthy.

Real-World Example: Form Input Validator

// form-validator.js

function validateField(name, value) {
  // Type guard โ€” ensure we have a string
  if (typeof value !== 'string') {
    return { valid: false, error: `${name} must be a string` };
  }

  const trimmed = value.trim();

  // Falsy check โ€” empty string is falsy
  if (!trimmed) {
    return { valid: false, error: `${name} is required` };
  }

  return { valid: true, value: trimmed };
}

function validateAge(value) {
  const num = Number(value);

  // NaN check
  if (Number.isNaN(num)) {
    return { valid: false, error: 'Age must be a number' };
  }
  if (!Number.isInteger(num) || num < 0 || num > 120) {
    return { valid: false, error: 'Age must be a whole number between 0 and 120' };
  }
  return { valid: true, value: num };
}

function validateForm(data) {
  const errors = [];

  // null / undefined check for required fields
  if (data.name == null) {   // catches both null and undefined
    errors.push('name field is missing');
  } else {
    const nameResult = validateField('Name', data.name);
    if (!nameResult.valid) errors.push(nameResult.error);
  }

  const ageResult = validateAge(data.age);
  if (!ageResult.valid) errors.push(ageResult.error);

  return { valid: errors.length === 0, errors };
}

// Tests
console.log(validateForm({ name: 'Alice', age: '28' }));   // valid: true
console.log(validateForm({ name: '',      age: '28' }));   // Name is required
console.log(validateForm({ name: 'Bob',   age: 'abc' }));  // Age must be a number
console.log(validateForm({ name: null,    age: '25' }));   // name field is missing
console.log(validateForm({ age: '25' }));                  // name field is missing

Common Mistakes

Mistake 1 โ€” Using typeof to check for null

โŒ Wrong โ€” typeof null returns ‘object’, not ‘null’:

if (typeof value === 'null') { ... }   // never true โ€” typeof null is 'object'

โœ… Correct โ€” use strict equality for null checks:

if (value === null) { ... }            // correct
if (value == null) { ... }             // catches both null AND undefined

Mistake 2 โ€” Treating empty array/object as falsy

โŒ Wrong โ€” [] and {} are truthy, so this condition always runs:

const items = [];
if (!items) {
  console.log('No items'); // Never runs โ€” [] is truthy!
}

โœ… Correct โ€” check the length for arrays, Object.keys() for objects:

if (items.length === 0) { console.log('No items'); } // correct

Mistake 3 โ€” Using isNaN() instead of Number.isNaN()

โŒ Wrong โ€” global isNaN() coerces its argument first, giving false positives:

isNaN('hello')         // true โ€” 'hello' coerces to NaN first
isNaN(undefined)       // true โ€” undefined coerces to NaN

โœ… Correct โ€” Number.isNaN() only returns true for actual NaN:

Number.isNaN('hello')   // false โ€” 'hello' is a string, not NaN
Number.isNaN(NaN)       // true โ€” this is actual NaN

▶ Try It Yourself

Quick Reference

Type typeof Check For It With
string 'string' typeof x === 'string'
number 'number' typeof x === 'number' && !Number.isNaN(x)
boolean 'boolean' typeof x === 'boolean'
undefined 'undefined' x === undefined or typeof x === 'undefined'
null 'object' โš ๏ธ x === null
array 'object' Array.isArray(x)
object (plain) 'object' typeof x === 'object' && x !== null
NaN 'number' โš ๏ธ Number.isNaN(x)

🧠 Test Yourself

Which of the following values is truthy in JavaScript?





โ–ถ Try It Yourself