A better typeof for Javascript

In Javascript, loosely typed as it is, you’ve surely run into a situation where you needed to control what kind of object you were dealing with. Maybe to make sure that AJAX call came back in proper order or perhaps to ensure that a user of your beatiful application didn’t do something stupid, like pass in a string when you expected an array. When that happened you probably reached for the typeof operator to establish the, well, type of object. But did you know that it is a severely flawed method? Like, to the point of uselessness flawed. Like George Bush – “We attacked because Iraq had WMDs”-flawed. Why, you say? Well, I’m glad you asked! The reason why typeof is crippled to the point that it surely deserves a place in the upcoming Amazon bestseller “JavaScript – The Bad Parts” is because it simply doesn’t do what it is supposed to! It’s really only good for one thing and that is to check if a value is undefined typeof foo === 'undefined'. If you try to use it to type other types of objects you should be prepared for some rather nasty surprises. Here are a few examples:


typeof 1.2 === 'number'
typeof NaN === 'number'
typeof new Number(1.2) === 'object'
typeof new Array(1 ,3, 5) === 'object'
typeof null === 'object'

Really JS, null is an object!? Well, I know that technically it is an object, but that typeof null = object really makes no sense! A fix for this was actually proposed for ECMAScript 5.1 but it was rejected since it would break backwards compatibility.

To be fair, there is some simple steps you can take to make typeof more reliable.

// NEVER USE THESE
typeof new Number(1.2) === 'object'
typeof new String('text') === 'object'
typeof new Boolean(true) === 'object'

// USE THIS
isNaN(numbr) === false && typeof numbr === 'number'
// TO PROTECT YOURSELF FROM
typeof numbr === 'number' // numbr is really NaN

// USE THIS
obj !== null && typeof obj === 'object'
// TO PROTECT YOURSELF FROM
typeof obj === 'object' // obj is really null

If you adhere to these guidelines there’s really only two significant problems left with typeof…

typeof [1,2,3] === 'object' // Can't type check for arrays

typeof /s/ === 'object' // RegExp is reported as an object in some browsers...
typeof /s/ === 'function' // and as a function in others...

So, what can be done to remedy these remaining faults? My standard way is this little gem of a function.

function is(obj, type) {
var test = Object.prototype.toString.call(obj).slice(8, -1);
return test === type;
}

is('test', 'String'); // true
is(new String('test'), 'String'); // true
is({}, 'Object'); // true
is(null, 'Object'); //false
is(null, 'Null'); // true
is([], 'Array'); // true
is(NaN, 'Number') // still true, gottdamnit!

That’s much better! The only edge case remaining is NaN, that still can only be detected via isNan(). But then again, NaN has always been the problem child of the Javascript family and has a serious identity crisis:

Nan === NaN // yup, as you suspected this is false

The is() function is one of the first I add to any new project and I use it whenever I need reliable type checking. What’s your take on this problem?