What are the primitive types in JavaScript, and how do you check which one a value is?
JavaScript has seven types in the language. Five of them are primitives, which are string, number, boolean, symbol, and bigint. The sixth type is the special one for values that were never assigned. The seventh type is object, and everything that is not a primitive is an object. That includes arrays, functions, dates, regular expressions, and instances of your own classes.
const samples = [
{ label: 'number', value: 42 },
{ label: 'string', value: '42' },
{ label: 'boolean', value: true },
{ label: 'null', value: null },
{ label: 'missing', value: undefined },
{ label: 'bigint', value: 10n },
{ label: 'symbol', value: Symbol('id') },
{ label: 'object', value: { a: 1 } },
{ label: 'array', value: [1, 2, 3] },
{ label: 'function', value: function () {} },
];
for (const sample of samples) {
console.log(sample.label + ' -> ' + typeof sample.value);
}
The typeof operator is the quick answer, and it is also the most misunderstood one. It returns function for functions, and it returns object for everything else that is not a primitive. That means a plain object and an array both report object. The null value is of the object type as well, so it also reports object. For a value that was never assigned, typeof returns the name of that special type as a piece of text.
There are two better tools when you need to be precise. The instanceof operator asks whether a value sits on a particular chain of prototypes, and that is the right test for your own classes. For anything that is built in, Object.prototype.toString.call(value) gives you the internal class name, so it tells an array apart from a plain object, and a date apart from a regular expression. The constructor property is a third option, but it can be faked easily with a plain object, so it is the least reliable of the three.
One point is worth saying out loud. There is no single primitive wrapper in JavaScript the way there is in Java. Numbers, strings, and booleans do have methods, but those methods live on the prototype of the wrapper object and not on the value itself.