When AI generates JavaScript, every value it creates has a type, and AI frequently gets type handling wrong. It mixes strings with numbers, forgets null checks, and uses loose equality. Understanding JavaScript's type system is how you catch these bugs before they ship.
The two families: Primitives vs Objects
JavaScript values fall into two categories. Primitives are simple, immutable values, strings, numbers, booleans. Objects are mutable collections that can hold multiple values. AI-generated code constantly moves between them, and knowing the difference is how you spot coercion bugs.
Primitive types (7 total)
Primitives are immutable. When you "change" a string, you're actually creating a new one:
const greeting = "hello";
const shout = greeting.toUpperCase();
console.log(greeting); // "hello" (unchanged!)
console.log(shout); // "HELLO" (new string)Here are all seven primitives:
| Type | Description | Example |
|---|---|---|
string | Text data | "hello", 'world', ` template |
| number | Integers and floats | 42, 3.14, -100 |
| boolean | True or false | true, false |
| null | Intentional absence of value | null |
| undefined | Uninitialized variable | undefined |
| symbol | Unique identifier (ES6+) | Symbol('id') |
| bigint | Arbitrary precision integers | 9007199254740991n` |
Object types
Objects are mutable collections that can hold multiple values:
// Plain object
const user = { name: "Alice", age: 25 };
// Array (special type of object)
const numbers = [1, 2, 3, 4, 5];
// Function (also an object!)
function greet() { return "Hello"; }Working with typeof
The typeof operator tells you what type a value is. But it has some quirks you need to know:
typeof "hello" // "string"
typeof 42 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof Symbol('id') // "symbol"
typeof 9007199254740991n // "bigint"
// Now the quirks:
typeof null // "object" (BUG! Should be "null")
typeof [] // "object" (arrays are objects)
typeof {} // "object"
typeof function(){} // "function" (special case)== instead of ===, or concatenate a string with a number expecting addition. When AI generates code that mixes types, especially around form inputs, API responses, or user data, always check whether it uses === for comparisons and explicit conversion (Number(), String()) before arithmetic.Checking for arrays
Since typeof [] returns "object", how do you check if something is an array?
const arr = [1, 2, 3];
// Modern way (ES6+)
Array.isArray(arr); // true
Array.isArray({}); // false
// Old way (don't use this)
arr instanceof Array; // true, but doesn't work across framesChecking for null
Since typeof null lies to us, use strict equality:
const value = null;
value === null; // true
typeof value === "object" && value !== null; // true (but why bother?)Dynamic typing in action
JavaScript is dynamically typed, meaning variables can hold any type and can change types:
let data = "hello"; // string
data = 42; // number
data = true; // boolean
data = { name: "Alice" }; // object
data = [1, 2, 3]; // arrayThis flexibility is powerful but can lead to bugs. TypeScript (which we'll cover later) adds static typing to catch these issues at compile time.
Type coercionWhat is type coercion?JavaScript automatically converting a value from one type to another during an operation, like turning a string into a number for subtraction. gotchas
Because of dynamic typing, JavaScript often converts types automatically:
console.log("5" + 3); // "53" (string concatenation)
console.log("5" - 3); // 2 (numeric subtraction)
console.log("5" * 3); // 15 (numeric multiplication)
console.log("5" == 5); // true (coerced equality)
console.log("5" === 5); // false (strict equality)When to use each type
| Use Case | Type | Example |
|---|---|---|
| User input, messages, IDs | string | const name = "Alice" |
| Counts, calculations, prices | number | const price = 19.99 |
| Flags, conditions, toggles | boolean | const isActive = true |
| Missing optional data | null | const middleName = null |
| Uninitialized variables | undefined | let data; |
| Unique object keys | symbol | const id = Symbol('userId') |
| Large integers | bigint | const huge = 12345678901234567890n |
| Complex data structures | object | const user = { name: "Alice" } |
| Ordered collections | array | const items = ["a", "b", "c"] |
null when you want to explicitly indicate "no value" (like clearing a form field). Use undefined when something hasn't been set yet (like a function parameter that wasn't provided). This distinction helps other developers understand your intent.Type checking in practice
Here's a robust pattern for checking types:
function processValue(value) {
if (value === null) {
console.log("Value is null");
} else if (value === undefined) {
console.log("Value is undefined");
} else if (Array.isArray(value)) {
console.log("Value is an array with " + value.length + " items");
} else {
console.log("Value is " + typeof value);
}
}
processValue(null); // "Value is null"
processValue(undefined); // "Value is undefined"
processValue([1, 2, 3]); // "Value is an array with 3 items"
processValue("hello"); // "Value is string"Quick reference
| Check | How | Gotcha |
|---|---|---|
| Is it a string? | typeof x === "string" | Works reliably |
| Is it a number? | typeof x === "number" | NaN is also a number |
| Is it null? | x === null | typeof null returns "object" |
| Is it an array? | Array.isArray(x) | typeof [] returns "object" |
| Is it undefined? | typeof x === "undefined" | Safe even if x is not declared |
// Primitives
const name = "Alice";
const age = 25;
const isStudent = true;
const nothing = null;
let notAssigned;
const uniqueId = Symbol('id');
const hugeNumber = 9007199254740991n;
// Objects
const user = { name: "Alice", age: 25 };
const hobbies = ["coding", "reading", "gaming"];
// Type checking
console.log(typeof name); // "string"
console.log(typeof age); // "number"
console.log(typeof isStudent); // "boolean"
console.log(typeof nothing); // "object" (quirk!)
console.log(typeof notAssigned); // "undefined"
console.log(typeof uniqueId); // "symbol"
console.log(typeof hugeNumber); // "bigint"
console.log(typeof user); // "object"
console.log(typeof hobbies); // "object"
// Better array checking
console.log(Array.isArray(hobbies)); // true
console.log(Array.isArray(user)); // false
// Null checking
console.log(nothing === null); // true