Posted over 3 years ago. Visible to the public. Repeats.

JavaScript: Testing the type of a value

Checking if a JavaScript value is of a given type can be very confusing:

  • There are two operators typeof and instanceof which work very differently.
  • JavaScript has some primitive types, like string literals, that are not objects (as opposed to Ruby, where every value is an object).
  • Some values are sometimes a primitive value (e.g. "foo") and sometimes an object (new String("foo")) and each form requires different checks
  • There are three different types for null (null, undefined and NaN) and each has different rules for equality.

Your project will often use a library like Lodash or Unpoly's up.util that will hide this inconsistency behind functions like _.isBoolean(x) or _.isObject(x). However, I encourage every JavaScript developer to understand what these functions do under the hood. This way you will be able to understand code that does not use LoDash, e.g. when debugging a library or when working on a project without LoDash.


This one is straightforward to test with typeof:

x = true typeof x === 'boolean' // => true


Strings can exist as literal ("foo") and as an object (new String("foo")), hence we cannot rely on typeof:

typeof "foo" // => "string" typeof new String("foo") // => "object"

Your test should check both forms:

x = 'foo' typeof x === 'string' || x instanceof String // => true


Numbers can exist as literal (123) and as an object (new Number(123)), hence we cannot rely on typeof:

typeof 123 // => "number" typeof new Number(123) // => "object"

Your test should check both forms:

x = 123 typeof x === 'number' || x instanceof Number // => true


x = function() {} typeof x === 'function' // => true

Note that classes (class Foo { ... }) are also functions. There is no easy way to test if an object is a class, especially when transpilation is involved.

An object with keys and values

When a developer talks about an "object" in JavaScript, she probably means a variable where you can assign values to keys. However, JavaScript has a different notion of what constitutes an "object". When a library has a function to test for an object, it detects the notion that is more useful to the developer.

Let's start with the easiest case, an Object or object literal. Here typeof returns "object", as expected:

x = {} = 'bar' // => 'bar' typeof x // => 'object'

However, you can also assign key/values on functions:

x = function() {} = 'bar' // => 'bar' typeof x // => 'function'

Finally JavaScript has a caveat that typeof null returns 'object'. No developer would consider this behavior useful, since you cannot assign keys or values to an object.

Taking into consideration all of the above, most libraries consider this to be a check for "object":

(typeof x === 'object' || typeof x == 'function') && (x !== null)


In JavaScript, Arrays are objects where the indexes are keys, and the elements are values.

If you want to check that an object is an array, you can use the static Array.isArray() method:

Array.isArray([1, 2, 3]) // => true Array.isArray({ foo: 'bar' }) // => false

Note that Array.isArray() returns false for array-like objects like jQuery collections or the NodeList returned by document.querySelectorAll().

Instances of a given class

Use instanceof to check if an object is an instance of the given class. It checks whether the object was constructed with the given constructor function.

class Foo {} x = new Foo() x instanceof Foo // => true

This also returns true if the object is an instance of the subclass of the given class:

class Foo {} class Bar extends Foo {} y = new Bar() y instanceof Foo // => true

Note that there is also, which returns the class name of the given instance as a string:

class Foo {} x = new Foo() === 'Foo' // => true

Comparing against has several drawbacks:

  • It relies on, which you need to polyfill for Internet Explorer
  • Asset minification will shorten all function names, breaking your comparison in the process. You can disable this in your minfier, costing you about 5% file size post-gzip.
  • It does not throw an error if you change the class name and forget to change the string

Duck typing

To check whether an object contains a property ("responds to a method" in Ruby lingo), use the in operator. It checks whether a property exists in the object or its prototype chain:

let parent = { parentKey: 1 } let child = Object.create(parent) child.childKey = 2 'childKey' in child // => true 'parentKey' in child // => true 'otherKey' in child // => false

Note that there is a difference between a property that is missing from an object, or a property being set to undefined:

let object = { foo: undefined } // => undefined // => undefined 'foo' in object // => true 'bar' in object // => false


Confusingly, typeof NaN returns "number". There is a built-in function isNaN(), but it also returns true for every other non-number value.

The appropriate check is this:

x = NaN typeof x === 'number' && isNaN(x) // => true


typeof null returns "object", so it is not very helpful here.

The appropriate check is to simply compare it with another null:

x = null x === null // => true


To check if a name is assigned the undefined value, compare it with another undefined:

x = undefined x === undefined // => true

This will crash if x was never declared as a name in the current scope:

// y was never declared y === undefined // Uncaught ReferenceError: y is not defined

When you want to check the value of a variable, crashing is exactly what you want.

If you really want to check if y is undeclared in the current scope (as opposed to being assigned the undefined value), you can use this:

// y was never declared typeof y === 'undefined' // => true
Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Henning Koch
Last edit:
11 months ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more