JavaScript Data Types: A Complete Beginner Guide

Master all JavaScript data types including primitives and objects. Learn how each type behaves, when to use them, and how to check types with typeof in practical, real-world code examples.

JavaScriptbeginner
12 min read

Every value in JavaScript belongs to a specific data type. Understanding these types is fundamental to writing code that behaves the way you expect. JavaScript has eight built-in data types: seven primitives and one non-primitive type (objects). This guide walks through each one with practical examples, explains how type checking works, and shows you how data types affect everyday operations like comparisons, function arguments, and storage.

If you are still getting comfortable with JavaScript variables, start there first. This article assumes you know how to declare variables with let and const.

The Eight JavaScript Data Types

JavaScript data types fall into two categories: primitive types and reference types. Primitives hold simple, immutable values. Reference types hold complex structures that can change.

CategoryTypeExampletypeof Result
PrimitiveString"hello""string"
PrimitiveNumber42, 3.14"number"
PrimitiveBigInt9007199254740991n"bigint"
PrimitiveBooleantrue, false"boolean"
PrimitiveUndefinedundefined"undefined"
PrimitiveNullnull"object" (historic bug)
PrimitiveSymbolSymbol("id")"symbol"
ReferenceObject{}, [], function(){}"object" or "function"
Why null Returns 'object'

The typeof null === "object" result is a well-known bug from JavaScript's first implementation in 1995. It was never fixed because changing it would break billions of lines of existing code. Always check for null explicitly with value === null.

Primitive Types in Detail

String

Strings represent text data. You can create them with single quotes, double quotes, or backtick template literals.

javascriptjavascript
const firstName = "Ada";
const lastName = 'Lovelace';
const greeting = `Hello, ${firstName} ${lastName}!`;
 
console.log(greeting); // "Hello, Ada Lovelace!"
console.log(typeof greeting); // "string"
console.log(greeting.length); // 20

Strings are immutable in JavaScript. Every string operation creates a new string rather than modifying the original.

javascriptjavascript
const original = "JavaScript";
const upper = original.toUpperCase();
 
console.log(original); // "JavaScript" (unchanged)
console.log(upper);    // "JAVASCRIPT" (new string)

Number

JavaScript uses a single Number type for both integers and floating-point values. It follows the IEEE 754 double-precision 64-bit format.

javascriptjavascript
const age = 25;
const price = 19.99;
const negative = -42;
const scientific = 2.998e8; // 299,800,000
 
console.log(typeof age);   // "number"
console.log(typeof price); // "number"

The Number type has three special values you should know:

javascriptjavascript
console.log(1 / 0);          // Infinity
console.log(-1 / 0);         // -Infinity
console.log("text" * 2);     // NaN (Not a Number)
console.log(typeof NaN);     // "number" (yes, NaN is a number type)

The safe integer range extends from -(2^53 - 1) to 2^53 - 1. Beyond these limits, precision is lost.

javascriptjavascript
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(9007199254740991 + 1);    // 9007199254740992
console.log(9007199254740991 + 2);    // 9007199254740992 (wrong!)

BigInt

When you need integers larger than Number.MAX_SAFE_INTEGER, use BigInt. Add an n suffix to any integer literal.

javascriptjavascript
const largeNumber = 9007199254740991n;
const anotherBig = BigInt("123456789012345678901234567890");
 
console.log(largeNumber + 1n); // 9007199254740992n (correct!)
console.log(typeof largeNumber); // "bigint"

BigInt cannot be mixed with regular numbers in arithmetic operations. You must convert explicitly.

javascriptjavascript
// This throws: TypeError: Cannot mix BigInt and other types
// const result = 10n + 5;
 
const result = 10n + BigInt(5); // 15n

Boolean

Booleans represent logical values: true or false. They drive every conditional and loop in JavaScript.

javascriptjavascript
const isLoggedIn = true;
const hasPermission = false;
 
console.log(typeof isLoggedIn); // "boolean"

Every JavaScript value can be converted to a boolean. Values that become false are called "falsy," and everything else is "truthy."

Falsy ValuesTruthy Values (examples)
falsetrue
0, -0, 0n1, -1, 3.14
"" (empty string)"hello", " " (space)
null{} (empty object)
undefined[] (empty array)
NaN"0" (string zero)

Undefined

A variable that has been declared but not assigned a value holds undefined. Functions that do not explicitly return a value also return undefined.

javascriptjavascript
let username;
console.log(username);       // undefined
console.log(typeof username); // "undefined"
 
function doNothing() {}
console.log(doNothing());   // undefined

Null

null represents an intentional absence of any value. Unlike undefined (which means "not yet assigned"), null means "explicitly empty."

javascriptjavascript
let selectedUser = null; // No user selected yet
 
console.log(selectedUser);       // null
console.log(typeof selectedUser); // "object" (the historic bug)

Use null when you want to deliberately clear a variable or signal "no value here."

Symbol

Symbols are unique, immutable identifiers introduced in ES2015. They are primarily used as object property keys that cannot collide with other keys.

javascriptjavascript
const id = Symbol("userId");
const anotherId = Symbol("userId");
 
console.log(id === anotherId); // false (every Symbol is unique)
console.log(typeof id);        // "symbol"
 
const user = {
  [id]: 12345,
  name: "Ada",
};
 
console.log(user[id]); // 12345

Reference Types: Objects

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

javascriptjavascript
const user = { name: "Ada", age: 25 };
const scores = [95, 87, 92, 88];
const greet = function (name) {
  return `Hello, ${name}!`;
};
 
console.log(typeof user);   // "object"
console.log(typeof scores); // "object"
console.log(typeof greet);  // "function"
console.log(Array.isArray(scores)); // true

The key difference between primitives and objects is that objects are stored by reference. When you assign an object to another variable, both variables point to the same data in memory.

javascriptjavascript
const original = { name: "Ada", role: "engineer" };
const copy = original;
 
copy.role = "architect";
console.log(original.role); // "architect" (both point to the same object!)

For a deeper exploration of how this affects your code, check the primitive vs reference types guide.

Type Checking with typeof

The typeof operator is the primary way to check data types at runtime. It returns a string indicating the type.

javascriptjavascript
console.log(typeof "hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);        // "object" (bug, check with === null)
console.log(typeof Symbol("x")); // "symbol"
console.log(typeof 10n);         // "bigint"
console.log(typeof {});          // "object"
console.log(typeof []);          // "object" (use Array.isArray())
console.log(typeof function(){}); // "function"

For robust type checking, combine typeof with specific checks:

javascriptjavascript
function getType(value) {
  if (value === null) return "null";
  if (Array.isArray(value)) return "array";
  return typeof value;
}
 
console.log(getType(null));      // "null"
console.log(getType([1, 2, 3])); // "array"
console.log(getType({ a: 1 }));  // "object"
console.log(getType("text"));    // "string"

Best Practices

Write Type-Safe JavaScript

These practices help you avoid the most common type-related bugs in JavaScript projects.

Use strict equality (===) for comparisons. The loose equality operator (==) performs type coercion, which can produce surprising results like 0 == "" returning true. Always use === to compare both value and type.

Check for null and undefined separately. Since typeof null returns "object", never rely on typeof alone to detect null. Use value === null for null checks and typeof value === "undefined" for undefined checks.

Use Array.isArray() for array detection. Since typeof [] returns "object", the only reliable way to check for arrays is Array.isArray(value).

Initialize variables with the correct type. Declare variables with the value type you intend to use. If you plan to store a number, initialize with 0 or NaN, not null or "". This makes your code's intent clear.

Prefer template literals for string building. Instead of concatenating strings with +, use backtick template literals. They handle type conversion automatically and are easier to read.

Common Mistakes and How to Avoid Them

Type-Related Pitfalls

These mistakes cause subtle bugs that are hard to track down in larger codebases.

Confusing null and undefined. Both represent "no value," but they have different semantics. undefined means a variable was declared but not assigned. null is an intentional empty value. Treating them interchangeably leads to inconsistent behavior in your APIs and functions.

Assuming typeof always identifies the type correctly. The typeof operator has quirks: typeof null is "object", typeof [] is "object", and typeof NaN is "number". Always use targeted checks for these edge cases.

Performing arithmetic on mixed types without conversion. JavaScript silently coerces types during arithmetic operations, which produces unexpected results like "5" + 3 returning "53" (string concatenation) instead of 8.

Comparing BigInt with Number using ===. Strict equality between BigInt and Number always returns false, even when the values are mathematically equal. Use loose equality (==) or convert explicitly.

javascriptjavascript
console.log(10n === 10); // false
console.log(10n == 10);  // true
console.log(10n === BigInt(10)); // true

Forgetting that NaN is not equal to itself. The only value in JavaScript where x !== x is NaN. Use Number.isNaN(value) to check for NaN reliably.

Next Steps

Explore [dynamic typing](/tutorials/programming-languages/javascript/what-are-dynamic-data-types-in-javascript)

Learn how JavaScript's dynamic type system works and why variables can hold any type at any time in the dynamic data types guide.

Understand memory storage

Discover how JavaScript stores primitive values on the stack and objects on the heap, and why this matters for performance and debugging.

Learn type conversion

Master implicit and explicit type conversion to understand how JavaScript automatically converts types during operations.

Practice with operators

Apply your data type knowledge to arithmetic, comparison, and logical operators with real examples.

Rune AI

Rune AI

Key Insights

  • Eight types total: seven primitives (String, Number, BigInt, Boolean, Undefined, Null, Symbol) plus Object
  • Primitives are immutable: operations on primitives create new values rather than modifying the original
  • typeof has quirks: typeof null returns "object" and typeof [] returns "object", so use targeted checks
  • Objects store by reference: assigning an object to a new variable creates a shared pointer, not a copy
  • Use strict equality: always prefer === over == to avoid implicit type coercion surprises
RunePowered by Rune AI

Frequently Asked Questions

How many data types does JavaScript have?

JavaScript has eight data types: seven primitives (String, Number, BigInt, Boolean, Undefined, Null, Symbol) and one non-primitive type (Object). Arrays, functions, dates, and regular expressions are all subtypes of Object.

What is the difference between null and undefined in JavaScript?

Undefined means a variable has been declared but not assigned a value, and it is the default state of uninitialized variables. Null is an explicitly assigned value that represents "intentionally empty." Both are falsy, but they have different types: `typeof undefined` is `"undefined"` and `typeof null` is `"object"` (a historic bug).

Why does typeof null return "object" in JavaScript?

This is a bug from JavaScript's original 1995 implementation by [Brendan Eich](/tutorials/programming-languages/javascript/who-invented-javascript-the-brendan-eich-story). Internally, values were represented with a type tag, and null used the same tag as objects (zero). A proposal to fix this (typeof null === "null") was rejected in 2006 because it would break too many existing websites.

When should I use BigInt instead of Number in JavaScript?

Use BigInt when you need to work with integers larger than `Number.MAX_SAFE_INTEGER` (9,007,199,254,740,991). Common use cases include cryptographic calculations, financial systems dealing with very large numbers, and database IDs that exceed the safe integer range. For everyday arithmetic, regular Number is sufficient.

Is JavaScript a strongly typed or weakly typed language?

JavaScript is weakly (loosely) typed, meaning the runtime automatically converts between types when needed. For example, `"5" * 2` produces `10` because JavaScript coerces the string to a number. This is different from strongly typed languages like Python or Java, which throw errors on type mismatches. TypeScript adds static type checking on top of JavaScript for developers who want stricter type safety.

Conclusion

JavaScript's eight data types form the foundation of every program you write, from simple scripts to complex web applications. Understanding the distinction between primitives and objects, knowing the quirks of typeof, and recognizing how type coercion works will save you hours of debugging. The most impactful habit is using strict equality (===) and targeted type checks (Array.isArray, Number.isNaN, === null) instead of relying on JavaScript's automatic type conversions.