Type checking in JavaScript is a minefield. typeof null === "object", NaN has type "number", and Array.isArray exists because typeof [] lies. Building type utilities from scratch tests whether you know which tool to reach for and when each one breaks.
What are Type Utilities?
Type-checking utilities (isString, isNumber, isArray, isPlainObject, etc.) are helpers that reliably determine what kind of value you're dealing with. JavaScript ships with three type-checking primitives — typeof, instanceof, and Object.prototype.toString.call() — and each has specific blind spots you need to know.
typeofis fast and works for primitives, but has the infamous bug:typeof null === "object". It also can't distinguish arrays from plain objects.instanceofchecks the prototype chain and handles custom classes, but breaks across execution contexts (iframes, different realms) because each realm has its own copy of built-in constructors.Object.prototype.toString.call(value)returns[object Type]— the most reliable check for built-in types ([object Array],[object Date], etc.) and the basis for most library-grade type checking.
The hardest utility is isPlainObject — distinguishing a plain {} from instances of Date, RegExp, Map, or custom classes. This requires inspecting the prototype chain: a plain object's immediate prototype is either Object.prototype or null (for Object.create(null)).
These utilities are foundational. Every library (Lodash, Ramda, etc.) ships its own set, and interviewers use them to test whether you understand JavaScript's type system quirks rather than just the API surface.
The Problem
"Implement a set of type-checking utilities: isString, isNumber, isBoolean, isNull, isUndefined, isArray, isObject, isFunction, and isPlainObject. Each should return true only for the type it claims to check."
Thought Process
JavaScript gives us three type-checking tools:
typeof— fast, works for primitives, buttypeof null === "object"andtypeof [] === "object"are both wronginstanceof— checks the prototype chain, works for custom classes, breaks across realms (iframes)Object.prototype.toString.call()— returns[object Type], the most reliable for built-in types
The interview tests whether you know which tool to use for which type. The rule of thumb: use typeof for primitives, Array.isArray for arrays, and Object.prototype.toString.call() for distinguishing plain objects from other objects.
Step 1 — typeof — What It Gets Right and Wrong
Loading editor...
Step 2 — Base Implementations
For primitives, typeof works — with special handling for null:
Loading editor...
The NaN question: Is NaN a number? typeof NaN === "number" is true, but most type-checking use cases want to exclude it. State your choice: "I'm excluding NaN because it represents an invalid number."
Step 3 — isArray and isObject
typeof fails for arrays. The reliable approach:
Loading editor...
Step 4 — isPlainObject
This is the hardest one. A "plain object" is an object created by {} or new Object() — not a Date, RegExp, Map, or instance of a custom class.
The most reliable check inspects the prototype chain:
Loading editor...
Step 5 — Edge Cases
-0 vs +0: typeof -0 === "number" is true. Usually you don't need to special-case this, but be aware of it.
NaN: Decide whether you include it in isNumber. Most utility libraries exclude it. State your choice.
Boxed primitives: new String("hello") has typeof "object". Most type-checking utilities treat this as an object, not a string. If needed, check with Object.prototype.toString.call(v) === "[object String]" but for strings specifically.
Cross-realm instanceof: If you use instanceof Array and the array comes from an iframe, it returns false because each realm has its own Array constructor. Array.isArray and Object.prototype.toString.call() don't have this problem.
Full Solution
Loading editor...
What Interviewers Are Testing
typeofquirks — you knowtypeof null === "object"and can explain it's a legacy bugNaNawareness — you knowtypeof NaN === "number"and have a position on whether to include it- Array detection — you know
typeof []won't work, andArray.isArrayis the solution - Plain object detection — you can distinguish
{}fromnew Date()using the prototype chain - Cross-realm issues — you know
instanceofbreaks across iframes
Complexity
| Function | Time | Space |
|---|---|---|
| All utilities | O(1) | O(1) |
Interview Tips
- Start with the three tools — name
typeof,instanceof, andObject.prototype.toString.call()before writing any code. This frames your approach. - Call out
typeof nullimmediately — "The first thing to know is thattypeof nullreturns"object"— so we need a special case." This shows you know the gotcha that trips up juniors. - Explain
isPlainObjectcarefully — this is where interviewers spend the most time. Walk through the prototype chain logic out loud. - Mention
Object.prototype.toString.call()as the fallback — even if you don't use it for every utility, knowing it exists and when to reach for it (e.g., distinguishing[object Date]from[object Object]) shows deeper knowledge.