Type checking helps you write solid JavaScript by letting you know exactly what kind of data you’re working with, whether it’s a number, string, array, or something else. JavaScript gives us several built-in tools for this, like typeof for quick type checks and instanceof for deeper prototype and inheritance tests.
However, these tools have quirks, and picking the right one is key for clean, bug-free code. This guide unpacks how these checks work, where they trip developers up, and how you can combine them to confidently handle any data type you encounter.
How typeof Works & What It Returns
The typeof operator gives you a quick way to check the type of a variable or value, always returning a string:
Corner Cases and Quirks of typeof
There are a few oddities to watch for with typeof:
- typeof null is "object" (a well-known historical JavaScript bug):
- typeof on undeclared identifiers returns "undefined" instead of throwing an error:
How instanceof Works: Prototypes & Inheritance
typeof vs instanceof: The Interview Question
When instanceof Fails: Frames & Prototypes
- If objects were created in different browser frames or windows, instanceof can fail, because their prototypes aren’t truly the same.
- Modifying __proto__ or manually changing the prototype can also confuse instanceof.
Reliable Type Checking: typeof, instanceof, and More
- Use typeof for primitives.
- Use Array.isArray() for arrays:
- Check for dates, maps, and sets with instanceof:
- For plain objects, you might use obj !== null && typeof obj === "object" && obj.constructor === Object.
Best Practices for Safe Type Checks (No TypeScript)
- Prefer typeof for simple primitive checks.
- Use instanceof for custom classes, arrays, or DOM objects.
- Always validate input, avoid relying on type checks for complete safety.
- Guard against null and undefined before using further property checks.
- For arrays, avoid typeof x === "object"—use Array.isArray(x).
Checking Complex Structures
- Arrays: Array.isArray(data)
- Dates: data instanceof Date
- Maps/Sets: data instanceof Map
- Plain objects: Object.prototype.toString.call(data) === "[object Object]"
