Mastering the Typeof Guard in TypeScript for Runtime Safety
Learn how to use the typeof guard in TypeScript to safely narrow union types at runtime. Improve your type safety and eliminate runtime errors today.

Previously in this course, we explored Type Narrowing with Conditionals in TypeScript to handle basic logic flow. While those techniques help us manage broad categories, we often encounter scenarios where we need to distinguish between specific data types—like a string versus a number—at runtime.
This is where the typeof guard comes in. It is one of the most fundamental tools for refining your types when you are dealing with Union Types for Flexibility in TypeScript.
What is a Typeof Guard?
In JavaScript, the typeof operator returns a string representing the type of an unevaluated operand. TypeScript leverages this existing JavaScript behavior to perform "control flow analysis."
When you use typeof inside a conditional block, TypeScript "narrows" the variable's type based on that check. This tells the compiler, "Inside this specific block, I have verified the data is a string, so treat it as such."
Why This Matters for Runtime Safety
TypeScript types disappear at compile time. However, our application often receives data from APIs or user inputs that could be one of several types. If you try to call .toUpperCase() on a value that might be a number, your code will crash at runtime. Using a typeof guard prevents these errors before they can reach your users.
Implementing Typeof Guards: A Worked Example

Imagine our task API client needs to handle a taskId that could arrive as either a string (a UUID) or a number (a legacy database ID).
TYPESCRIPTtype TaskIdentifier = string | number; function getTaskDetails(id: TaskIdentifier) { // TypeScript doesn't know if id is string or number here // id.toUpperCase(); // Error: Property CE9178">'toUpperCase' does not exist on type CE9178">'number' if (typeof id === "string") { // Inside this block, TypeScript knows id is a string console.log(CE9178">`Fetching task with UUID: ${id.toUpperCase()}`); } else { // Inside this block, TypeScript knows id must be a number console.log(CE9178">`Fetching task with legacy ID: ${id.toFixed(0)}`); } }
By adding that typeof check, we’ve effectively "guarded" our code. We have narrowed the union type TaskIdentifier into its specific components, allowing us to safely call methods specific to those types.
Hands-on Exercise
Update your task client logic. Create a function called formatAssignee that accepts a parameter which can be a string (a name) or null (if unassigned).
- Write the function to accept
string | null. - Use a
typeofguard to check if the value is a string. - If it is, return the name in uppercase.
- If it is null, return the string
"Unassigned".
Common Pitfalls
Even experienced engineers trip up on these nuances. Keep these two rules in mind:
- The
typeof nullQuirk: In JavaScript,typeof nullreturns"object". This is a long-standing language bug. If you are checking fornull, do not usetypeof. Use a direct comparison likeif (val === null). - Over-guarding: You don't need to use a guard if TypeScript already knows the type. If you have already narrowed a type earlier in the function, don't add redundant
typeofchecks; it makes your code harder to read. - Objects and Arrays:
typeofisn't very helpful for distinguishing between different object shapes (e.g., distinguishing aTaskobject from aUserobject). For those scenarios, we will look at more advanced techniques like theinoperator, which we'll cover in the next lesson.
Frequently Asked Questions
Does typeof work on custom interfaces?
No. typeof only recognizes JavaScript primitives (string, number, bigint, boolean, symbol, undefined, object, and function). For custom interfaces, you'll need TypeScript Type Guards: Stop Runtime Data Corruption in API Calls.
Can I use typeof with const variables?
Yes, but since const variables often have narrow literal types, the compiler will often infer the type automatically without needing a guard. Guards are most useful for function parameters or variables with union types.
Recap
The typeof guard is your primary defense when dealing with mixed-type data. By wrapping your logic in a simple conditional check, you provide the compiler with the information it needs to ensure type safety. You’ve now moved from guessing what a variable might be to explicitly verifying it at runtime.
Up next: The In Operator for Object Narrowing.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.

React & Next.js Dashboard / Admin UI Development
A clean, data-rich dashboard UI in React or Next.js — charts, tables, and real-time data that your users will actually enjoy using.


