Primitive types and typeof
Name the seven primitive types and the object type, and use typeof while knowing where it gives odd answers.
What you will learn
- Name JavaScript's seven primitive types
- Use typeof and recognise its two famous quirks
- Explain what dynamic and weak typing mean in JavaScript
On this page
Every value in a JavaScript program has a type, and the type decides what you can do with the value. The general ideas, such as what a type is and the difference between static and dynamic typing, are in the fundamentals lesson on values and types. This lesson lists the types JavaScript actually has and the operator that reports them.
The seven primitives and objects
JavaScript has seven primitive types. A primitive is a single, simple value that cannot be changed from the inside. Everything else is an object.
| Type | Example | Holds |
|---|---|---|
undefined |
undefined |
A variable that has no value yet |
null |
null |
A deliberate “no value” |
| boolean | true, false |
Yes or no |
| number | 42, 3.14, NaN |
All ordinary numbers, whole or fractional |
| bigint | 10n |
Whole numbers of any size |
| string | "text" |
Text |
| symbol | Symbol("id") |
A unique value, used as a hidden key |
Objects cover everything else: plain objects {} (a record with named parts), arrays [] (an ordered list), functions, dates, maps and so on. Arrays and functions are objects too, with extra abilities. They get their own lessons, starting with arrays and objects. In this lesson you only need to recognise them.
Note that there is only one type for ordinary numbers. 42 and 3.14 are both number. There is no separate integer type. The next lesson explains what that means.
typeof
The typeof operator gives back the type of a value as a string.
console.log("typeof 42:", typeof 42);console.log("typeof 3.14:", typeof 3.14);console.log('typeof "text":', typeof "text");console.log("typeof true:", typeof true);console.log("typeof undefined:", typeof undefined);console.log("typeof null:", typeof null);console.log("typeof 10n:", typeof 10n);console.log('typeof Symbol("id"):', typeof Symbol("id"));console.log("typeof {}:", typeof {});console.log("typeof []:", typeof []);console.log("typeof console.log:", typeof console.log);console.log("typeof NaN:", typeof NaN);typeof 42: numbertypeof 3.14: numbertypeof "text": stringtypeof true: booleantypeof undefined: undefinedtypeof null: objecttypeof 10n: biginttypeof Symbol("id"): symboltypeof {}: objecttypeof []: objecttypeof console.log: functiontypeof NaN: numbertypeof is an operator, not a function, so typeof 42 needs no parentheses. They are harmless, and sometimes needed to group an expression.
Three results deserve a second look.
typeof nullis"object". This is a mistake from the first version of the language that can never be fixed without breaking old programs.nullis a primitive. To test for it, compare directly withvalue === null.typeof []is"object". An array is an object. UseArray.isArray(value)to find out whether something is an array.typeof NaNis"number".NaNstands for “not a number”, and it is still a value of the number type. The next lesson explains how it arises.
A function such as console.log reports "function", even though functions are objects underneath. That is a convenience, not a separate type.
Telling null, arrays and objects apart
Because typeof calls all three "object", use a direct test for each. This program checks three values with both approaches:
const nothing = null;const list = [1, 2];const record = { a: 1 };
console.log(typeof nothing === "object", nothing === null);console.log(typeof list === "object", Array.isArray(list));console.log(typeof record === "object", Array.isArray(record));true truetrue truetrue falseIn each line the first answer comes from typeof and is true every time, so it tells you nothing. The second answer separates the cases: === null finds the null, and Array.isArray finds the array. Once you have learned functions, you can wrap these tests in a helper of your own.
Names that do not exist
Reading a variable that was never declared throws a ReferenceError. But typeof is safe on such a name, and answers "undefined". It is how code checks whether a runtime feature exists, as the first lesson did with window. The one exception is a let or const name that is declared later in the same block: typeof on it throws too. The lesson on let and const explains why.
Dynamic and weak typing
In JavaScript the type belongs to the value, not to the variable. A variable can hold a number now and a string a moment later. The keyword let declares a variable that can be given a new value; the lesson on let and const covers it.
let value = 5;console.log(typeof value);
value = "five";console.log(typeof value);
console.log(typeof neverDeclared);numberstringundefinedThat is called dynamic typing. Nothing checks types before the program runs, so a type mistake shows up as wrong behaviour or a runtime error. TypeScript, a separate language that compiles to JavaScript, adds static checks.
JavaScript is also weakly typed: operators accept values of the wrong type and quietly convert them, so "5" * 2 gives 10 instead of an error. The coercion lesson shows the rules.
Primitives and wrapper objects
A primitive has no properties of its own, yet "text".length and "text".toUpperCase() work. The language briefly wraps the primitive in an object to look the property up, then discards the wrapper. You never have to think about this, with one exception: you can create a wrapper by hand with new String(...), and you should not.
console.log(typeof "text", typeof new String("text"));console.log("text".length, "text".toUpperCase());string object4 TEXTA new String("text") is an object that behaves differently in comparisons and conditions. Write plain "text".
Common pitfalls
- Testing for null with typeof.
typeof value === "object"is also true fornull, arrays and every plain object. - Treating
NaNas “not a number” in the type sense. Its type isnumber. - Using
new Number,new Stringornew Boolean. Use the plain values. CallNumber(...),String(...)andBoolean(...)withoutnewwhen you want to convert. - Expecting a variable to keep its type. Nothing stops a reassignment from changing it.
Without running anything, write down what each line prints, then run the program and compare.
console.log(typeof 0);console.log(typeof "0");console.log(typeof 0n);console.log(typeof null);console.log(typeof undefined);console.log(typeof NaN);console.log(typeof []);console.log(typeof {});console.log(typeof Math.max);console.log(typeof Symbol("x"));console.log(typeof true);console.log(typeof typeof 42);console.log(typeof Infinity);Input: none. Expected output: 13 lines, from number to number, with null, [] and {} all giving object.
Show solution
console.log(typeof 0);console.log(typeof "0");console.log(typeof 0n);console.log(typeof null);console.log(typeof undefined);console.log(typeof NaN);console.log(typeof []);console.log(typeof {});console.log(typeof Math.max);console.log(typeof Symbol("x"));console.log(typeof true);console.log(typeof typeof 42);console.log(typeof Infinity);numberstringbigintobjectundefinednumberobjectobjectfunctionsymbolbooleanstringnumbertypeof typeof 42 is typeof "number", which is "string": the inner typeof returns a string. Math.max is a function, and Infinity is a number.
typeof also works on the result of a calculation. Predict the type of each of these eight results, then print them.
5 + "5"5 * "2"5 > 3String(5)Number("5")"a" * 210n * 2n1 / 0
Input: none. Expected output, one per line: string, number, boolean, string, number, number, bigint, number.
Show solution
console.log(typeof (5 + "5"));console.log(typeof (5 * "2"));console.log(typeof (5 > 3));console.log(typeof String(5));console.log(typeof Number("5"));console.log(typeof ("a" * 2));console.log(typeof (10n * 2n));console.log(typeof (1 / 0));stringnumberbooleanstringnumbernumberbigintnumber+ with a string joins text, so the first result is a string. * always works on numbers, so "5" * 2 is the number 10 and "a" * 2 is NaN, which is still a number. A comparison gives a boolean. 1 / 0 is Infinity, also a number.
Declare const maybe = null;. Print two lines: first typeof maybe, then the result of testing maybe with === null. Then change the declaration to const maybe = undefined; and run it again.
Input: none. Expected output for null: object and true. Expected output for undefined: undefined and false.
Show solution
const maybe = null;
console.log(typeof maybe);console.log(maybe === null);objecttrueWith undefined the program prints undefined and false. Only the direct comparison tells null from a missing value reliably, because typeof null is "object".
Summary
- JavaScript has seven primitive types (
undefined,null, boolean, number, bigint, string, symbol) and the object type for everything else. typeofreturns a string. Remembertypeof null === "object"andtypeof [] === "object". Use=== nullandArray.isArrayinstead.- Types belong to values, not variables, and operators convert between them when they can.
Next: numbers and BigInt.