DEV Community

Glad Chinda
Glad Chinda

Posted on

JavaScript Tip: whatis() — A better typeof

Correctly determining the type of a value in JavaScript is not very obvious, especially to beginners. However, using Object.prototype.toString has always proven to yield a slightly better result for most values than the native typeof operator.

Leveraging Object.prototype.toString, we can create a better typeof — a function called whatis(), like so:

function whatis (value) {
  return Object.prototype.toString.call(value)
    .replace(/^\[object\s+([a-z]+)\]$/i, '$1')
    .toLowerCase();
}

Here, we are doing 3 things:

  • First, call Object.prototype.toString() on value to get the string tag of the value. The function returns a string of this format: "[object T]", where T is the string tag (e.g Array, String, WeakMap, etc).

  • Next, use a regular expression and String.prototype.replace() to extract the string tag.

  • Finally, change the string tag to all lowercase and return the result.

Note:
The whatis() function is still error prone. Its type testing mechanism is not so reliable for some kinds of built-in or program defined objects, since there are several ways of changing the reported type of an object.

whatis(NaN); // 'number'
whatis(-5.23); // 'number'
whatis(Infinity); // 'number'
whatis(144705209n); // 'bigint'
whatis('hello world'); // 'string'
whatis(Symbol.iterator); // 'symbol'

whatis(null); // 'null'
whatis(false); // 'boolean'
whatis(undefined); // 'undefined'

whatis(/^.+$/); // 'regexp'
whatis([1, 2, 3, 4]); // 'array'
whatis({ x: 5, y: 10 }); // 'object'
whatis(function () {}); // 'function'

whatis(new Date()); // 'date'
whatis(window.location); // 'location'
whatis(document.body); // 'htmlbodyelement'

Note:
The whatis() function will throw a ReferenceError for variables that have not been declared, unlike the typeof operator that evaluates to "undefined" for undeclared variables.

console.log(typeof undeclaredVar); // "undefined"
console.log(whatis(undeclaredVar)); // Throws ReferenceError

Further Reading

  1. typeof - JavaScript | MDN
  2. JavaScript typeof: Understanding type-checking in JavaScript
  3. Understanding the JavaScript typeof Operator ← Alligator.io
  4. Typeof | freeCodeCamp Guide

❤️ Like and Share

If you found this post insightful in any way please:

  • Like this post
  • Comment your feedback
  • Share with someone
  • Follow me on Twitter

Discussion (8)

Collapse
savagepixie profile image
SavagePixie

The whatis() function will throw a ReferenceError for variables that have not been declared, unlike the typeof operator that evaluates to "undefined" for undeclared variables.

Why not add a test for undefined then?

function whatis (value) {
  return value === undefined
    ? undefined
    : Object.prototype.toString.call(value)
      .replace(/^\[object\s+([a-z]+)\]$/i, '$1')
      .toLowerCase();
}
Collapse
gladchinda profile image
Glad Chinda Author • Edited on

Adding a test for undefined doesn't still solve the undeclared variable problem. In JavaScript, as much as I know, accessing an undeclared variable will always throw a ReferenceError. The only exception being with the typeof operator, where it evaluates to "undefined".

The typeof operator behaves such that it should never throw an error for any valid JavaScript value used as its operand, including an undeclared variable.

That said, running the modified function you defined above with an undeclared variable will still throw a ReferenceError.

Collapse
bbarbour profile image
Brian Barbour • Edited on

Undefined is a primitive type in Javascript. Understanding it and what it means is fundamental to the language. I'm very curious, why would you want to avoid returning it?

Collapse
gladchinda profile image
Glad Chinda Author

The primary focus of this post is handling type checking in JavaScript. For a very long time, relying on the typeof operator has been very problematic, especially for null, arrays, undeclared variables, etc.

For example, an undeclared identifier is not the same as a variable that is set to undefined. However, typeof operator reports both as "undefined". So how does one make the distinction? That is the essence of this post.

The technique described in the post is very popular for detailed type checking. However, as mentioned in the post, it is not completely error proof.

Collapse
bbarbour profile image
Brian Barbour

Gotcha! Makes sense. Thanks for clarifying.

Collapse
georgewl profile image
George WL

Not me that thinks this whole thing is surplus to requirements?

Collapse
gladchinda profile image
Glad Chinda Author

When you say requirements, what do you really mean?

Collapse
georgewl profile image
George WL

just that I think for most purposes it's using an anvil when all that's needed is a hammer :)