JavaScript Data Type Check Cheatsheet
Tags: javascript, datatypes, es6, webdev
Published: 2019-09-01 18:55:52

---
title: JavaScript Data Type Check Cheatsheet
published: true
tags: JavaScript, data types, es6, webdev
canonical_url: https://codewithhugo.com/javascript-data-type-check-cheatsheet/
---

> JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
> 
> [MDN Web Docs - JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)

Detailed in this post are common JavaScript data type checks, pitfalls and idiomatic workarounds.

## Classic JavaScript Data Type Checks

Here’s a collection of the most common data type checks in JavaScript. Whether you want to check if a variable contains a Date, a Promise, a plain old JavaScript object or an Array, it’s all here.

Everything from primitive types like number, boolean, string to detecting functions.

### Check if JavaScript variable contains an object

`typeof` does output `'object'` for objects.

It also does so for `null` and Arrays.

```
const object = {};

console.log(typeof object); // 'object'
console.log(typeof null); // 'object'
console.log(typeof []); // 'object'

console.log(object instanceof Object); // true
console.log(null instanceof Object); // false
console.log([] instanceof Object); // true

```

What’s more, much like in the case of Arrays, if there is inter-frame communication, it tends to share objects and arrays (see [JavaScript array type check - “is array” vs object in-depth](https://dev.to/hugo__df/detecting-object-vs-array-in-javascript-by-example-297d)). Therefore, checking whether something is a simple object vs an instance of a class is difficult.

In JavaScript you’ll notice that everything is an Object, and when you try to access a property that doesn’t exist, it’ll fail quietly (ie. return `undefined`):

```
console.log('aaaaa'.noProperty); // undefined
console.log([].nothing); // undefined

```

In idiomatic JavaScript code, we leverage this property to be just defensive enough, for example if we expect an object that has a `growl` method, but something else might be passed in:

```
function safeGrowl(anything) {
  if (anything.growl) {
    anything.growl()
  }
}

safeGrowl('hello'); // nothing
safeGrowl({ growl() { console.log('Growl!') }}); // Growl!

```

The moral of the story is: don’t check that something is an object, check that it has the properties you need (that’s what’s called [duck typing](https://en.wikipedia.org/wiki/Duck_typing)).

### Check if a value is a string in JavaScript

For strings, we can use a `typeof` check.

Much the same as for object checks, JavaScript won’t fail loudly when you try to use something as a string that isn’t a string, it will tend to just coerce it or call `.toString` on it.

```
const string = 'Hello World';
console.log(typeof string); // 'string'

// Implicit coercion to string using templates
const helloCount = 2;
const newString = `Hello number ${helloCount} at ${new Date('2019-06-23T21:00:26.861Z')}`;

console.log(newString);
// 'Hello number 2 at Sun Jun 23 2019 22:00:26 GMT+0100 (British Summer Time)'

```

This works with dates, number. For arrays and other objects that don’t directly implement a toString method, I would suggest using JSON.stringify.

```
const myArray = ['a', 'b', 'c'];
const mySimpleObject = { key: 'value' };

console.log(`${myArray} ${mySimpleObject}`); // 'a,b,c [object Object]'
console.log(`${JSON.stringify(myArray)} ${JSON.stringify(mySimpleObject)}`)
// '["a","b","c"] {"key":"value"}'

```

### Check if a value is a JavaScript Number/Integer

JavaScript Numbers are a bag of fun. They’ve got a similar gotcha to `object` checks, that’s the `NaN` (Not a Number) value. `NaN` usually is the output of trying to do arithmetic where one of the operands is not a Number.

The quirks of `NaN` is that it’s not equal to itself, and it’s actually a Number, just like `Infinity` and `- Infinity`

```
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false

console.log(typeof NaN); // 'number'
console.log(typeof Infinity); // 'number'
console.log(typeof -Infinity); // 'number'
console.log(typeof 123); // 'number'

```

#### Checking that a Number is not `NaN` (Not A Number)

One `NaN` check would just be:

```
const a = NaN;

function isNotANumber(maybeNotANumber) {
  return maybeNotANumber === maybeNotANumber;
}

isNotANumber(a); // true

```

The recommended approach is the following, there’s a built-in `Number.isNaN` function:

```
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN('abc')); // false
console.log(Number.isNaN(1234)); // false
console.log(Number.isNaN(123.11)); // false
console.log(Number.isNaN(true)); // false

```

The difference between `Number.isNaN` and the `isNaN` global is that `Number.isNaN` checks that the value passed in is a Number _and_ it is `NaN`.

The older global `isNaN` function just goes for the literal check that something is not a number.

```
console.log(isNaN(NaN)); // true
console.log(isNaN('abc')); // true
console.log(isNaN(1234)); // false
console.log(isNaN(123.11)); // false
console.log(isNaN(true)); // false

```

#### Check if a JavaScript variable contains an Integer

To check that JavaScript variable (or value) is an integer, we can use `Number.isInteger`:

```
console.log(Number.isInteger(123)); // true
console.log(Number.isInteger(12.3)); // false
console.log(Number.isInteger(123.0)); // true

```

#### Check if a JavaScript variable contains a useable Number value

To check that we’ve got a useable input value, we should check that the type is `number` and that the value is not NaN:

```
function isValidNumber(maybeNumber) {
  return typeof maybeNumber === 'number' && !Number.isNaN(maybeNumber);
}

console.log(isValidNumber('aaaaa')); // false
console.log(isValidNumber(NaN)); // false
console.log(isValidNumber(123)); // true
console.log(isValidNumber(1.23)); // true

```

### Check if a value is a boolean

As with JavaScript string and number data types, in JavaScript the pattern is to assume something is a boolean (or cast it to boolean) rather than checking that it’s a boolean. That’s because in JavaScript we can use logical operators with non boolean values due to the loose typing, this is usually explained through the concept of “truthiness” and “falsiness”.

> When JavaScript is expecting a boolean and it is given one of the values below, it will always evaluate to “falsy”
> 
> [MDN Web Docs - Falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)

The values in question (falsy values) are: `false`, `0`, `''` (or other empty string), `null` and `undefined`. Any other value will be evaluated to true.

There are some cases where `false` means something other than `undefined`, in that case, it’s possible to check that a value is falsy _and_ a boolean by using the `typeof`:

```
console.log(typeof true); // 'boolean'
console.log(typeof false); // 'boolean'

```

### Check if a variable contains an Array

To check if a JavaScript variable is an Array, there’s a built-in `Array.isArray`.

The fun gotcha with JavaScript Arrays is that they’re just objects.

```
console.log(([]) instanceof Object); // true
console.log(typeof []); // 'object'

```

A way to duck-type an Array is to use existence of a `.length` property. However this can be pretty weak since there’s nothing enforcing that Arrays should be the only type to have a `.length` property. The pattern tends to look like so:

```
function processList(maybeArray) {
  if (!maybeArray.length) {
    return []
  }
  return maybeArray.map(i => i); // literally copy
}

```

Now this code doesn’t actually check that `maybeArray` is an Array. It sort of does that but in the same line of code ie. `!maybeArray.length`, it also states that `maybeArray` must have a non-falsy length, ie. in the case where it _is_ in fact an Array, it shoul also not have length 0 (must not be empty).

It’s trivial to trick the above and make it crash on `.map` with for example using the following data: `{ length: 'aaaa' }`. That’s not the point, if consumers of this function are trusted, this kind of check can be fine.

Using Array.isArray however works as follows:

```
console.log(Array.isArray({})); // false
console.log(Array.isArray(new Map())); // false
console.log(Array.isArray(new Set())); // false

console.log(Array.isArray([])); // true
console.log(Array.isArray(new Array())); // true

```

For a closer look at the internals of how we check for Arrays, see [JavaScript array type check - “is array” vs object in-depth](https://dev.to/hugo__df/detecting-object-vs-array-in-javascript-by-example-297d). The big gotcha with built-in JavaScript data types like Array, Object and Date in JavaScript is that communicating between frames means the constructors and therefore `instanceof` checks don’t work.

### Check if an object is an instance of a specific class/constructor function

Say you’ve got a set variable and you want to check that it’s a React Component, you can do:

```
import React, { Component } from 'react';

const myComp = new Component();

function isReactComponent(maybeComponent) {
  return maybeComponent instanceof Component;
}

isReactComponent(myComp);
// true

isReactComponent({});
// false

```

This also works with constructor functions:

```
function Dog (name) {
  this.name = name
}

const max = new Dog('Max');

console.log(max instanceof Dog); // true

```

Another interesting thing is it works all the way up the prototype chain/class hierarchy:

```
console.log(({}) instanceof Object); // true
console.log((new Dog) instanceof Object); // true

```

### Check if an object is an Error

`Error` is just a constructor/class. So in the same way we could check for `React.Component` or `Dog` class:

```
function isError(maybeError) {
  return maybeError instanceof Error;
}

isError(new Error('Something went wrong')); // true
isError(new EvalError()); // true
isError(new InternalError()); // true
isError(new RangeError()); // true
isError(new ReferenceError()); // true
isError(new SyntaxError()); // true
isError(new TypeError()); // true
isError(new URIError()); // true

```

See more about [Fundamental Objects on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference#Fundamental_objects).

### Check for a valid JavaScript Date string (parseable date-string)

```
function isValidDateString(maybeDateString) {
  return !Number.isNaN(Number(new Date(maybeDateString)));
}

console.log(isValidDateString('abcd')); // false
console.log(isValidDateString(1234)); // true
console.log(isValidDateString('2019-06-23T22:00:26.861Z')); // true

```

The above function doesn’t actually check whether something is a valid string but whether it’s convertible to a valid date.

For most intents and purposes, it _will_ catch dodgy date strings, and has the benefit of not being unreadable at the cost of allow number timestamps to be passed in. A more apt name might be `isConvertibleToDate`. Disallowing numbers would just be a case of adding a `typeof maybeDateString === 'string'`.

### Check for a valid JavaScript Date

To check whether or not something is a valid, we’ll just take the same approach as checking whether it’s convertible to a date

```
function isValidDateObject(maybeDate) {
  return (
    typeof maybeDate === 'object' &&
    !Number.isNaN(Number(new Date(maybeDate))
  );
}

isValidDateObject('abc'); // false
isValidDateObject(1234); // false
isValidDateObject('2019-06-23T22:00:26.861Z'); // false
isValidDateObject(new Date('2019-06-23T22:00:26.861Z')); // true

```

You could also apply the `instanceof` approch:

```
function isValidDateObject(maybeDate) {
  return maybeDate instanceof Date;
}

isValidDateObject('abc'); // false
isValidDateObject(1234); // false
isValidDateObject('2019-06-23T22:00:26.861Z'); // false
isValidDateObject(new Date('2019-06-23T22:00:26.861Z')); // true

```

This has some cross-frame issues and you never know when someone might mess with the global `Date` to replace it with their own custom, non-standard version.

### Check if a JavaScript variable is a Promise

Promise checks are done using `instanceof` with all the usual cross-frame or custom implementation caveats:

```
console.log({} instanceof Promise); // false

```

With Promises there’s also the issue for then-ables. Which for most intents and purposes may as well be Promises but which won’t pass our above check.

In async/await-enabled environments, you’ll also note that `await`-ing a function that doesn’t return a Promise doesn’t cause any unintended side-effects, the return value of the function (even if it’s not an async function), can be stored the same way as you would if you hadn’t `await`-ed.

### Check if a JavaScript variable is a function

As mentioned on the MDN Web Docs JavaScript is a “programming language with [first-class functions](https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function)”. First-class functions, just means functions are treated like any other variable.

```
console.log(typeof (() => {})); // 'function'
console.log(typeof function () {}); // 'function'
function myFunc () {}
console.log(typeof myFunc); // 'function'

```

Refer to the object example to see how an idiomatic “run this function if it exists” would look.

## Debugging JavaScript Data Type Issues

What does each of the following look like when it’s `console.log`-ed?

One of the big issues is that `console.log` tends to stringify whatever object it’s passed using its `.toString()` method. A lot of the time, a combination of pattern matching, logging out `typeof` and logging out a `JSON.stringify`-ed version of the object gives good results.

### Figuring out if something is a Promise

Forgot to `await` a function that returns a Promise (including an `async` function).

You usually want to do something with the output of the Promise:

#### A promise that’s supposed to return a list

```
const fetchList = async () => ['first-item'];

async function doSomething() {
  const [firstItem] = fetchList();
}

doSomething()
// UnhandledPromiseRejectionWarning:
// TypeError: fetchList is not a function or its return value is not iterable

```

#### A promise that’s supposed to return an object

```
const fetchObj = async () => ({ property: 'value' });

async function doSomething() {
  const obj = fetchObj();
  console.log(obj.property);
  console.log(obj);
  console.log('done')
}

doSomething()
// undefined
// Promise {
// { property: 'value' },
// and so on

```

### Debugging Array vs Array-like

There are a few Array-like objects in JavaScript for example `arguments`, `NodeList`s (output of `document.querySelectorAll`).

The first thing to do is to just log them out:

```
const anchors = document.querySelectorAll('a');
console.log(anchors); // { "0": {}, "1": {} }

function multiVariateFn() {
  console.log(arguments)
}

multiVariateFn(1, 2, 3); // [Arguments] { '0': 1, '1': 2, '2': 3 }

```

Compare those outputs to:

```
console.log([1, 2, 3]); // [1, 2, 3]

```

Here is the old-school method of converting them to regular `Array`-s (which means you can use Array.forEach/.map etc.):

```
const anchors = Array.prototype.slice.call(
  document.querySelectorAll('a'),
  0
);

function multiVariateFn() {
  const args = Array.prototype.slice.call(arguments, 0);
  return args.reverse();
}

console.log(multiVariateFn(1, 2, 3, 4)); // [4, 3, 2, 1]
console.log(multiVariateFn('a', 'b', 'c')); // ['c', 'b', 'a']

```

The ES6 approach would look something closer to this, they take advantage of array spread syntax and rest parameters syntax respectively.

```
const anchors = [...document.querySelectorAll('a')];

function multiVariateFn(...args) {
  return args.reverse();
}

console.log(multiVariateFn(1, 2, 3, 4)); // [4, 3, 2, 1]
console.log(multiVariateFn('a', 'b', 'c')); // ['c', 'b', 'a']

```

A more conservative approach could leverage `Array.from` (see [Array from MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)):

```
const anchors = Array.from(document.querySelectorAll('a'));

function multiVariateFn() {
  return Array.from(arguments).reverse();
}

console.log(multiVariateFn(1, 2, 3, 4)); // [4, 3, 2, 1]
console.log(multiVariateFn('a', 'b', 'c')); // ['c', 'b', 'a']

```

## Source Materials - Further Reading

While creating this JavaScript Data Type Check guide, I took inspiration from some of the top relevant posts:

- [http://tobyho.com/2011/01/28/checking-types-in-javascript/](http://tobyho.com/2011/01/28/checking-types-in-javascript/)
- [https://webbjocke.com/javascript-check-data-types/](https://webbjocke.com/javascript-check-data-types/)
- [https://ultimatecourses.com/blog/understanding-javascript-types-and-reliable-type-checking](https://ultimatecourses.com/blog/understanding-javascript-types-and-reliable-type-checking)

As well as the [MDN Web Docs for JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript).

[<svg xmlns="http://www.w3.org/2000/svg" style="height:12px;width:auto;position:relative;vertical-align:middle;top:-2px;fill:white" viewbox="0 0 32 32"><title>unsplash-logo</title>
<path d="M10 9V0h12v9H10zm12 5h10v18H0V14h10v9h12v-9z"></path></svg>Daniel Fazio](https://unsplash.com/@danielfazio?utm_medium=referral&utm_campaign=photographer-credit&utm_content=creditBadge "Download free do whatever you want high-resolution photos from Daniel Fazio")