The typeof operator in JavaScript evaluates and returns a string with the data type of an operand. For example, to find the type of 123, we would write -

typeof 123  

This will return a string with the type of 123, which, in this case, will be "number". In addition to "number", the typeof operator can return one of 6 potential results -

typeof 123 // "number"  
typeof "abc" // "string"  
typeof true // "boolean"  
typeof {a: 1} // "object"  
typeof function foo() {} // "function"  
typeof undefined // "undefined"  
typeof Symbol('foo') // "symbol"  

In the above examples, it's pretty straightforward what the type of the operands will be. However, there are a few cases where it is unclear or misunderstood what the type of the operand should be.

What's the typeof typeof 123?

typeof typeof 123 // "string"  

What is the type of a typeof expression? Well, the typeof operator always returns a string with the type of the operand passed to it. If the resultant type of the expression is, for example, a number, what will be returned is "number". This means that, regardless of resultant type, the type of a typeof [any operand], will always be a string.

What's the typeof NaN?

typeof NaN // "number"  

The type of NaN, which stands for Not a Number is, surprisingly, a number. The reason for this is, in computing, NaN is actually technically a numeric data type. However, it is a numeric data type whose value cannot be represented using actual numbers. So, the name "Not a Number", doesn't mean that the value is not numeric. It instead means that the value cannot be expressed with numbers.

This also explains why not all NaN values are equal. For example -

const NaN1 = 2 * "abc";  
const NaN2 = 2 * "abc";

NaN1 === NaN2 // false  

Those two NaN values are not equal because they are not necessarily the same unrepresentable number.

What's the typeof [1,2,3]?

typeof [1,2,3] // "object"  

The typeof an array is an object. In JavaScript, arrays are technically objects; just with special behaviours and abilities. For example, arrays have a Array.prototype.length property, which will return the number of elements in the array. Arrays also have special methods, e.g. Array.prototype.push() or Array.prototype.unshift() (See JavaScript Array Methods - Mutator Methods).

To differentiate an Array object from an Object object, we can use the Array.isArray() method.

Array.isArray( [1,2,3] ) // true  
Array.isArray( { a: 1 } ) // false  

What's the typeof null?

typeof null // "object"  

The null value is technically a primitive, the way "object" or "number" are primitives. This would typically mean that the type of null should also be "null". However, this is not the case because of a peculiarity with the way JavaScript was first defined.

In the first implementation of JavaScript, values were represented in two parts - a type tag and the actual value. There were 5 type tags that could be used, and the tag for referencing an object was 0. The null value, however, was represented as the NULL pointer, which was 0x00 for most platforms. As a result of this similarity, null has the 0 type tag, which corresponds to an object.

What's the typeof class Foo {}?

typeof class Foo {} // "function"  

Finally, we have Classes. Classes were introduced in ES2015 (ES6) as a better syntax for prototype-based inheritance. Before Classes, to make an inheritable object, we would have to use a function.

function Dog() { }  
Dog.prototype.bark = function() {  

const snoopy = new Dog();  
snoopy.bark() // alert("woof!")  

With Classes, we can create the same object this way -

class Dog {  
    bark() {

const snoopy = new Dog();  
snoopy.bark() // alert("woof!")  

However, Classes have always just been a syntactical wrapper around the function method. The same function is actually being created, but just with the author writing it in a different, cleaner way. This is why the typeof a Class, is still just a Function.