Skip to content
exercises
JavaScript

A better typeof

Object.prototype.toString and friends.

BasicCourse

Implement a typeOf function that returns accurate type strings for all JavaScript values — including the ones typeof gets wrong.

The Problem

typeof has some well-known gaps:

typeof null; // 'object' — wrong
typeof []; // 'object' — not specific enough
typeof new Date(); // 'object' — not specific enough
typeof /regex/; // 'object' — not specific enough

For real type checking, you need Object.prototype.toString.

The Implementation

function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
typeOf(null); // 'null'
typeOf([]); // 'array'
typeOf(new Date()); // 'date'
typeOf(/regex/); // 'regexp'
typeOf(42); // 'number'
typeOf("hello"); // 'string'
typeOf(undefined); // 'undefined'
typeOf({}); // 'object'
typeOf(() => {}); // 'function'

Object.prototype.toString.call(value) returns a string like "[object Array]". .slice(8, -1) removes the [object prefix and ] suffix. .toLowerCase() normalizes the casing.

Why call Is Needed

toString can be overridden on any object. Calling it via Object.prototype.toString.call(value) bypasses any override and uses the original implementation, which inspects the internal [[Class]] tag.

Extended Version

function typeOf(value) {
if (value === null) return "null";
if (Array.isArray(value)) return "array";
return typeof value;
}

This shorter version handles the most common gaps without Object.prototype.toString. Use whichever level of precision you need.

Why It Matters

typeof is fine for primitives. For anything more complex — runtime type guards, serialization, debugging utilities — you need the full picture.