← all labs  ·  ← prev lab  ·  next lab →

Foundation Lab 03

Values, Types & typeof

Before variables, functions, or objects can make sense, we need to know what kinds of things JavaScript actually deals in — and where the tool for asking "what kind of thing is this" quietly lies to you.

What this lab produces: no files, no commit — a pure concept lab. You'll run one short snippet in a console or with node.
Concept type: Common Concept, JavaScript-Specific Rules
◇
VALUES & TYPES 1 of 10

Every language needs some way to represent and tell apart different kinds of information. This lab is JavaScript's answer.

Mental Models

A value carries a type tag with it A box holding 42, with a small attached tag reading number. 42 number

Mental Model 1 of 5The Value Carries the Type

typeof asks the value, not the variable A variable box points at a value box; typeof reads the value's tag, skipping the variable name entirely. count 7 "number"

Mental Model 2 of 5typeof Follows the Arrow

Seven small primitive types, one big object bucket Seven small tags on the left, one large box labeled object on the right. string number boolean undefined null symbol bigint object

Mental Model 3 of 5Two Families, Not One

An analogy: the material is stamped on the package, not the shipping label A package stamped GLASS sits inside a shipping label sleeve; the label can be peeled off and replaced without changing what the package is made of. GLASS label A

Mental Model 4 of 5An Analogy: The Stamp Is on the Package

Common misconception: typeof reads code, not the running value A magnifying glass hovers over a line of source code with an X, then over a running value box with a check mark. ✕ source text ✓ live value

Mental Model 5 of 5Misconception: typeof Doesn't Read Your Code

Learning Objectives

  1. Objective 1 of 4 — I can name all seven JavaScript primitive types and explain what falls under the single "object" catch-all instead.
  2. Objective 2 of 4 — I can explain why a JavaScript variable's type can change over its lifetime, and how that's different from a statically-typed language.
  3. Objective 3 of 4 — I can predict what typeof returns for a given value — including the null and function special cases — and explain why each behaves that way, not just recite the answer.
  4. Objective 4 of 4 — I can write a "is this actually a usable object" check that isn't fooled by typeof null === "object".

Pre-Lab Quiz

Answer from intuition first. This lab has a well-known trick question in it on purpose.

Question 1 of 5Once a variable is assigned a number, can that same variable later hold a string instead?Open question

Question 2 of 5Guess: what does typeof null return?Open question

Question 3 of 5Is a function value a fundamentally different type from a plain object, or a special case of one?Open question

Question 4 of 5let x = 5; then later x = "hello"; — does that second line cause any kind of type error?Open question

Question 5 of 5Guess: does typeof give arrays their own result, separate from plain objects?Open question


The Concept

"Type" is not a JavaScript invention

A type is simply a category that tells you what kind of thing a piece of data is, and therefore what you're allowed to do with it — you can add two numbers, but adding two booleans (true/false values) doesn't mean the same thing conceptually. Every mainstream programming language needs some notion of type for exactly this reason: without it, the language (or you) would have no way to know whether an operation on a piece of data even makes sense.

What's JavaScript-specific is which types exist, how loosely they're enforced, and what the built-in typeof operator — a small piece of syntax, like + or -, that takes a value and produces a result, in this case a string naming that value's type — will and won't tell you correctly about them.

Cross-language note

Common concept: every value has a type.

Python: has separate int and float types, plus str, bool, NoneType, and checks types with type()/isinstance().

JavaScript: has exactly one numeric type, number, for both whole and decimal values (Lab 34 covers the precision consequences of that), and checks types with the typeof operator — which, as Question 2 above showed, has at least one well-known bug baked in.

Seven primitives, one catch-all

JavaScript has exactly seven primitive types. "Primitive" here just means a value the language treats as a single, indivisible piece of data — you can't reach "inside" it to change a piece of it; any change produces a brand-new value instead. The seven are: string (text), number (both whole and decimal numbers), boolean (true/false), undefined and null (two different flavors of "nothing" — Lab 04 is entirely about that distinction), symbol (a guaranteed-unique value, used as a rare kind of identifier), and bigint (whole numbers too large for the regular number type to represent precisely).

Everything else in the language — plain {} objects, arrays, functions, dates, and anything else you can build with new or a literal — falls under one single, broad type: object. That split (the third mental-model diagram above) matters a lot more once we get to how values are copied and compared (Lab 21), but for now it's just the map of what exists.

Why does a typeof operator even need to exist?

In a statically-typed language, the compiler already knows every variable's type before the program ever runs, so it can catch a type mistake ahead of time and refuse to compile. JavaScript has no such compile-time check — a variable's type is only knowable by looking at whatever value it currently holds, while the program is running. That's exactly the gap typeof fills: it's a way for your running code to ask, at that exact moment, "what kind of thing am I holding right now?" and branch accordingly. Without it, code that needs to behave differently for a string versus a number would have no reliable way to tell them apart at all.

function describe(value) {
  if (typeof value === "string") {
    return "a piece of text";
  }
  if (typeof value === "number") {
    return "a number";
  }
  return "something else";
}

What typeof actually checks, and where it's wrong

typeof value reports a string naming the value's type — but it has two long-standing quirks worth knowing up front, not stumbling into later:

  1. typeof null returns "object", not "null". This is a bug from the language's original 1995 implementation that was never fixed, because fixing it would break existing code across the web. It does not mean null behaves like an object — trying to read a property off null throws an error immediately.
  2. typeof a function returns "function", even though a function is, underneath, an object (something Lab 11 covers directly). It's a convenience label, not evidence of a separate fundamental type.

The practical consequence of quirk #1: a check like typeof x === "object", meant to mean "x is a real object I can use," will also silently match x = null — which is not something you can actually use like an object. The safe version adds an explicit exclusion: typeof x === "object" && x !== null.


Lab

Primary objective: predict what typeof reports for a spread of values, including the two quirky ones above.

You'll need: a browser console or node — no project, no files.

Lab 1 of 1 — Probe typeof across a spread of values

Task

Predict, then check, what typeof reports for nine different values.

Instructions

Step 1 of 4

// Paste this into a scratch file or console. Read it — do not run it yet.

console.log(typeof "hello");
console.log(typeof 42);
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof null);
console.log(typeof Symbol("id"));
console.log(typeof 10n);
console.log(typeof {});
console.log(typeof function () {});

This step is complete when: you've written down a guess for all nine lines, including the two you think might be surprising.

Step 2 of 4

Write your nine predictions, then reveal.

This step is complete when: you've run the snippet yourself and it matches the revealed output.

Step 3 of 4

// Edit the file yourself. Don't paste finished code — type it from these comments.

// Add one more console.log(typeof ...) call, checking an
// array literal, e.g. [1, 2, 3].

// Add a second one checking new Date().

This step is complete when: both new lines are added to your file, after the existing nine.

Step 4 of 4

Predict what both new lines report, then run and compare — then answer this comprehension check before moving on: given typeof [1, 2, 3], why doesn't typeof have a separate "array" result the way it has a separate "function" result?


Comprehension Checklist

  • I can name all seven primitive types without looking them up.
  • I can explain why typeof null === "object" without calling it "just how JavaScript works" — I know it's a historical bug, not a rule to reason from.
  • I know a function is a type of object, not a separate fundamental type, even though typeof labels it specially.
  • I know typeof tells me about the current value, not the variable — the same variable name can hold different types over its life.
  • I can write typeof x === "object" && x !== null from memory as the safe version of an object check.

Post-Lab Quiz

These are different questions from the pre-lab quiz — they test what the experiment should have taught you, not the same questions again.

Question 1 of 5What does typeof [1, 2, 3] return?Open question

Question 2 of 5You want to check that a value is a real, usable object — not null. Which check is correct?Open question

Question 3 of 5let value = someCondition ? 42 : "42"; — before running this, can you say for certain what typeof value will be, just by reading the source code?Open question

Question 4 of 5Which of these does typeof NOT report as "object": {}, [], null, function(){}?Open question

Question 5 of 5let x = "hello"; then x = 100; — what does typeof x report now, and what would it have reported right before the reassignment?Open question


Reflection Questions

Write your own answer first — the blurred text is one possible answer, not the only correct one.

Reflection 1 of 3. If you've used a language with fixed variable types before, what's the biggest adjustment in reasoning this "type belongs to the value, not the variable" model requires?

Reflection 2 of 3. Now that you know typeof null is wrong, where might you have previously trusted it without noticing?

Reflection 3 of 3. In your own words, explain to an imaginary coworker why "typeof reads the code" is wrong and "typeof reads the live value" is right. What's a one-sentence example that proves it?


What Breaks If This Understanding Is Wrong?

If you think a variable "is a number" rather than "currently holds a number," reassignment bugs will look mysterious. And if you don't know typeof null === "object" is a bug, you'll eventually write a null-check using typeof x === "object" that silently also matches null — a classic, hard-to-spot source of crashes.

What JavaScript Concept Was Learned Today?

JavaScript's eight types (seven primitives plus object), and where the built-in typeof operator can and can't be trusted.

Relates to: ◇ Values & Types (1 of 10) — this experiment demonstrated JavaScript's specific answer to "how does the language represent and distinguish kinds of information."


Next

Lab 04 zooms in on one specific corner of this type system: the different ways JavaScript represents "nothing." You now know undefined and null are two of the eight types from today — next we'll see exactly how they differ from each other, and from a name that was never declared at all.

← All labs  ·  Lab 04 — undefined, null & Undeclared Identifiers →