The typeof
operator in JavaScript is full of strange quirks. Before I show you what to watch out for let's take a look at what it does correctly.
First of all, typeof
will always return a string that (supposedly) describes what follows it. Here are some examples that work as expected, with the resulting string shown in a comment following each statement:
typeof undefined; // 'undefined'
typeof true; // 'boolean'
typeof 42; // 'number'
typeof 'foo'; // 'string'
typeof function () {}; // 'function'
typeof { foo: bar }; // 'object'
So far, so good. But what about using typeof
on an array?
typeof [foo, bar]; // 'object'
Well, okay, arrays are technically objects in JavaScript, so that's cool, I guess.
What about null
?
typeof null; // 'object'
So that's, uh, also an object? Okay, sure.
What about a class?
typeof class baz {}; // 'function'
So a class is a function? Again, technically true, but maybe not the result we were expecting.
What about NaN
, which literally stands for "not a number"?
typeof NaN; // 'number'
Oh, JavaScript, you precious thing.
Now that you know to watch out for those unexpected results, let's talk about how to get some more useful information from unknown types.
The Object
class in JavaScript has a toString
method prototype that can be called directly to produce a string that's a bit more descriptive and useful:
Object.prototype.toString.call(undefined); // '[object Undefined]'
Object.prototype.toString.call(true); // '[object Boolean]'
Object.prototype.toString.call(42); // '[object Number]'
Object.prototype.toString.call('foo'); // '[object String]'
Object.prototype.toString.call(function () {}); // '[object Function]'
Object.prototype.toString.call({ foo: bar }); // '[object Object]'
Object.prototype.toString.call([foo, bar]); // '[object Array]'
Object.prototype.toString.call(null); // '[object Null]'
Much better. We can now tell the difference between an object, an array, and null
!
Alas, this method still falls short when it comes to classes and NaN
:
Object.prototype.toString.call(class baz {}); // '[object Function]'
Object.prototype.toString.call(NaN); // '[object Number]'
The class situation makes sense; classes in JavaScript are really just fancy syntax for special functions, but it would be nice to see something like [object Class]
returned here all the same. Oh well.
So, be careful when using typeof
, and use Object.prototype.toString.call()
if you need something a bit more descriptive.