Javascript Icon Get 57% off the JavaScript Master Bundle!

See the bundle then add to cart and your discount is applied.

0 days
00 hours
00 mins
00 secs

Understanding JavaScript types and reliable type checking

Type checking in JavaScript can often be a pain, especially for new JS developers. I want to show you how to reliably check types in JS and understand them a little more. This post digs through Objects, Primitives, shadow objects/coercion, the typeof operator and how we can reliably get a “real” JavaScript type.

Objects versus Primitives

“Everything in JavaScript is an Object”. Remember it, then forget it. It’s not true. JavaScript makes the subject very difficult to understand though - it presents everything as some form of “object” if we dive into their Prototypes (later). For now, let’s look at types.

To understand JavaScript types, we need a top level view of them:

  • Number
  • String
  • Boolean
  • Object
  • Null
  • Undefined

We have Number, String, Boolean - these are Primitives (not Objects!). This means their values are unable to be changed because they are merely values, they have no properties. The Primitive types are wrapped by their Object counterparts when called, JavaScript will dive between the Number/String/Boolean to an Object when needed (coercion). Underneath, it will infact construct an Object, use it, then return the result (all the instance will be shipped out for garbage collection).

For example using 'someString'.trim(); will spin up an Object underneath and call the .trim() method on it.

Null and undefined are weird (both Primitives too), and distinguish between no value or an unknown value (null is unknown value, undefined is totally not known or even declared). There is also an Error object.

Object’s however are a different story. You’ll notice I’ve not mentioned Array or RegExp, these are types of Object, let’s investigate. Under the Object tree we have:

  • Object
    • Function
    • Array
    • Date
    • RegExp

Having broken it down, things seem a little simpler, we have Objects versus Primitives. That’s it, right? No, JavaScript decided it wanted to complicate everything you’d assume logical from above.

JavaScript Array Methods eBook Cover

🎉 Download it free!

Ready to go beyond ForEach? Get confident with advanced methods - Reduce, Find, Filter, Every, Some and Map.

  • Green Tick Icon Fully understand how to manage JavaScript Data Structures with immutable operations
  • Green Tick Icon 31 pages of deep-dive syntax, real-world examples, tips and tricks
  • Green Tick Icon Write cleaner and better-structured programming logic within 3 hours

As an extra bonus, we'll also send you some extra goodies across a few extra emails.

Typeof operator

From MDN: “The typeof operator returns a string indicating the type of the unevaluated operand”.

Based on our newly acquired knowledge from the above, you wouldn’t expect this to happen:

typeof []; // object
typeof {}; // object
typeof ''; // string
typeof new Date() // object
typeof 1; // number
typeof function () {}; // function
typeof /test/i; // object
typeof true; // boolean
typeof null; // object
typeof undefined; // undefined

Whyyyyyy?! Function is an Object, but tells us it’s a function, Array is an Object and says it is. null is an Object, and so is our RegExp. What happened?

The typeof operator is a bit strange. Unless you know how to really use it, simply avoid it to avoid headaches. We wouldn’t want something like this to happen:

var person = {
  getName: function () {
    return 'Todd';
if (typeof person === 'object') {

// because I stupidly refactored some code changing the names
// but the `if` still lets through `person`
var person = [];
var myPerson = {
  getName: function () {
    return 'Todd';
if (typeof person === 'object') {
  person.getName(); // Uncaught TypeError: undefined is not a function 

typeof let us down here, what we really wanted to know was that person was a plain Object.

True Object types

There’s a really simple way, though to look at it looks like a hack:;

The .toString() method is accessed using Object.prototype because every object descending from Object prototypically inherits it. By default, we get [object Object] when calling {}.toString() (an Object).

We can use .call() to change the this context (as it converts its argument to a value of type) and, for example, if we use .call(/test/i) (a Regular Expression) then [object Object] becomes [object RegExp].

Which means if we run our test again using all JS types:[]); // [object Array]{}); // [object Object]''); // [object String] Date()); // [object Date]; // [object Number] () {}); // [object Function]; // [object RegExp]; // [object Boolean]; // [object Null]; // [object Undefined]

We can then push this into a function and more reliably validate our previous function:

var getType = function (elem) {
if (getType(person) === '[object Object]') {

To keep things DRY and save writing === '[object Object]' or whatever out each time, we can create methods to simply reference. I’ve used .slice(8, -1); inside the getType function to remove the unnecessary [object and ] parts of the String:

var getType = function (elem) {
  return, -1);
var isObject = function (elem) {
  return getType(elem) === 'Object';
if (isObject(person)) {


I put together all the above methods into a micro-library called Axis.js which you can use:

axis.isArray([]); // true
axis.isObject({}); // true
axis.isString(''); // true
axis.isDate(new Date()); // true
axis.isRegExp(/test/i); // true
axis.isFunction(function () {}); // true
axis.isBoolean(true); // true
axis.isNumber(1); // true
axis.isNull(null); // true
axis.isUndefined(); // true

The code powering that does some cool stuff for those interested:

/*! axis v1.1.0 | (c) 2014 @toddmotto | */
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
  } else if (typeof exports === 'object') {
    module.exports = factory;
  } else {
    root.axis = factory();
})(this, function () {

  'use strict';

  var exports = {};

  var types = 'Array Object String Date RegExp Function Boolean Number Null Undefined'.split(' ');

  var type = function () {
    return, -1);

  for (var i = types.length; i--;) {
    exports['is' + types[i]] = (function (self) {
      return function (elem) {
        return === self;

  return exports;


Thank you for reading!

Free eBooks:

JavaScript Array Methods eBook Cover

Ready to go beyond ForEach? Get confident with advanced methods - Reduce, Find, Filter, Every, Some and Map.

NestJS Build a RESTful CRUD API eBook Cover

Build your first NestJS app. With the CLI you'll learn the basics of real-world NestJS development.