VOOZH about

URL: https://blog.logrocket.com/how-to-use-type-guards-typescript/

⇱ How to use type guards in TypeScript - LogRocket Blog


2024-01-15
1954
#typescript
Oyinkansola Awosan
96803
πŸ‘ Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

Editor’s note: This article was last updated on 15 January 2024 to include the use of the TypeScript is operator. It also now covers the creation of custom type guards and information about how to inspect objects with type guards.

πŸ‘ How To Use Type Guards In TypeScript

A type guard is a TypeScript technique used to get information about the type of a variable, usually within a conditional block. Type guards are regular functions that return a Boolean, taking a type and telling TypeScript if it can be narrowed down to something more specific. Type guards have the unique property of assuring that the value tested is of a set type depending on the returned Boolean.

TypeScript uses built-in JavaScript operators like typeof, instanceof, and in to determine if an object contains a property. Type guards enable you to instruct the TypeScript compiler to infer a specific type for a variable in a particular context. This process validates that the type of an argument aligns with the specified type, enhancing type accuracy and code reliability.

Type guards are typically used for narrowing a type and are quite similar to feature detection, allowing you to detect the correct methods, prototypes, and properties of a value. Therefore, you can easily figure out how to handle that value.

πŸš€ Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

The instanceof type guard

instanceof is a built-in type guard that can be used to check if a value is an instance of a given constructor function or class. With this type guard, we can test if an object or value is derived from a class, which is useful for determining the type of an instance type.

The basic syntax for the instanceof type guard is below:

objectVariable instanceof ClassName;

In the example below, we see an example of the instanceof type guard:

interface Accessory {
 brand: string;
 }
 class Necklace implements Accessory{
 kind: string;
 brand: string;
 constructor(brand: string, kind: string) { 
 this.brand = brand;
 this.kind = kind;
 }
 }
 class bracelet implements Accessory{
 brand: string;
 year: number;
 constructor(brand: string, year: number) { 
 this.brand = brand;
 this.year = year;
 }
 }
 const getRandomAccessory = () =>{
 return Math.random() < 0.5 ?
 new bracelet('cartier', 2021) :
 new Necklace('choker', 'TASAKI');
 }
 let Accessory = getRandomAccessory();
 if (Accessory instanceof bracelet) {
 console.log(Accessory.year);
 }
 if (Accessory instanceof Necklace) {
 console.log(Accessory.brand); 
 }

The getRandomAccessory function above returns either a Necklace or bracelet object, as they both implement the Accessory interface. The constructor signatures for both Necklace and bracelet are different, and the instanceof type guard compares both constructor signatures to effectively determine the type.

The typeof type guard

The typeof type guard is used to determine the type of a variable. The typeof type guard is said to be very limited and shallow; it can only determine the following types recognized by JavaScript:

  • boolean
  • string
  • bigint
  • symbol
  • undefined
  • function
  • number

For anything outside of this list, the typeof type guard simply returns object.

The typeof type guard can be written in the following two ways:

typeof v !== "typename"
#or 
typeof v === "typename"

typename can be a string, number, symbol, or boolean.

In the example below, StudentId has a string | number type union parameter entry. We see that if the variable is a string, Student is printed, and if it is a number, Id is printed. The typeof type guard helps us to extract the type from x:

function StudentId(x: string | number) {
 if (typeof x == 'string') {
 console.log('Student');
 }
 if (typeof x === 'number') {
 console.log('Id');
 }
}
StudentId(`446`); //prints Student
StudentId(446); //prints Id

The in type guard

The in type guard checks if an object has a particular property, using that to differentiate between different types. It usually returns a Boolean, which indicates if the property exists in that object. It is used for its narrowing features, as well as to check for browser support.

The basic syntax for the in type guard is below:

propertyName in objectName

In the example below, the in type guard checks if the property house exists. In cases where it does exist, the Boolean true is returned, and where it does not exist, false is returned:

"house" in { name: "test", house: { parts: "door" } }; // => true
"house" in { name: "test", house: { parts: "windows" } }; // => true
"house" in { name: "test", house: { parts: "roof" } }; // => true
"house" in { name: "test" }; // => false
"house" in { name: "test", house: undefined }; // => true

Another similar example of how the in type guard works is shown below:

interface Pupil {
 ID: string;
 }
 interface Adult {
 SSN: number;
 }
 interface Person {
 name: string;
 age: number;
 }
 let person: Pupil | Adult | Person = {
 name: 'Britney',
 age: 6
 };
 const getIdentifier = (person: Pupil | Adult | Person) => {
 if ('name' in person) {
 return person.name;
 }
 else if ('ID' in person) {
 return person.ID
 }
 return person.SSN;
 }

The is operator

The is operator checks if a value or variable is of a specific type. It is a type guard that can be used to narrow the type of a variable or expression. It is often used with a user-defined type guard function to narrow down the type of a variable within a specific code block.

This operator allows you to check whether a value is a certain type at runtime by type testing. This is particularly useful when you want to ensure that a variable has a specific type before performing certain operations on it.

The basic syntax for the is operator is as follows:

variablename is typename

Here is a simple example of the is operator in action:

interface Cat {
 meow(): void;
}
interface Dog {
 bark(): void;
}
function isCat(pet: Dog | Cat): pet is Cat {
 return (pet as Cat).meow !== undefined;
}
let pet: Dog | Cat;
// Using the 'is' keyword
if (isCat(pet)) {
 pet.meow();
} else {
 pet.bark();
}

The code above checks the type of the variable pet and performs different actions based on its type. If pet is of type Cat, it calls the meow() method. If pet is of type Dog, it calls the bark() method.

The isCat() function is a type guard that checks if pet is of type Cat by checking if the meow() method exists on pet. If it does, the function returns true, indicating that pet is of type Cat. Otherwise, it returns false. The is keyword is used to perform the type check in the if statement.

Equality narrowing type guard

Equality narrowing checks for the value of an expression. For two variables to be equal, they must both be of the same type. If the type of a variable is unknown, but it is equal to another variable with a precise type, then TypeScript will narrow the type of the first variable with the information the well-known variable provides:

function getValues(a: number | string, b: string) {
 if(a === b) {
 // this is where the narrowing takes place. narrowed to string
 console.log(typeof a) // string
 } else {
 // if there is no narrowing, type remains unknown
 console.log(typeof a) // number or string
 }
}

If variable a is equal to variable b, then both have to have the same type. In this case, TypeScript narrows it down to string. Without narrowing, the type of a is still unclear because it could either be a number or a string.


Over 200k developers use LogRocket to create better digital experiences

πŸ‘ Image
Learn more β†’

Custom type guard with predicate

Creating a custom type guard is typically the most powerful option for using type guards. When you create a custom type guard by writing it yourself, there are no limits to what you can check. However, if the custom type guard is written incorrectly, it can cause many errors. Therefore, precision is key.

An example of a custom type guard is shown below:

interface Necklace{
 kind: string;
 brand: string;
}
interface bracelet{
 brand: string;
 year: number;
}
type Accessory = Necklace | bracelet;

const isNecklace = (b: Accessory): b is Necklace => {
 return (b as Necklace).kind !== undefined
}
const Necklace: Accessory = {kind: "Choker", brand: "TASAKI"};
const bracelet: Accessory = {brand: "Cartier", year: 2021};
console.log(isNecklace(bracelet)) //Logs false
console.log(isNecklace(Necklace)) //Logs true

In the code above, the type predicate b is Necklace will make TypeScript reduce the type to Necklace instead of returning just a Boolean value.

Custom type guards

TypeScript custom type guards are functions that enable you to check the type of a value or expression at runtime. They are useful for verifying more complex types or conditions that can’t be easily checked using built-in type guards like some we have already explored.

Custom type guards can be used in conditional expressions and other parts of your code where you need to check the type of a value or expression.

Custom type guards allow you to check for more complex types and conditions and generally improve the readability of your code.

Here is an example of a custom type guard:

function isBaby(obj: any): obj is Baby {
 return typeof obj === "object" && obj !== null && "sound" in obj;
 }

 interface Baby {
 sound: string;
 }

 function makeSound(baby: any) {
 if (isBaby(baby)) {
 console.log("Making a sound:", baby.sound);
 } else {
 console.log("Not a valid baby.");
 }
 }

Above, the function makeSound takes the argument baby of type any. It checks if the baby object satisfies the isBaby type guard, which checks if the object has a property called sound. If the baby object satisfies the isBaby type guard, it logs the sound of the baby to the console. Otherwise, it logs β€œNot a valid baby.” to the console.

isBaby is our custom type guard function. It checks if an object has a sound property, which is characteristic of a baby.

Using TypeScript type guards for object type verification

Type guards can be used to inspect or check the type of an object. Type guards can be used to check the specific properties an object has, thus allowing us to perform operations specific to those properties.


More great articles from LogRocket:


We can also use type guards to check if an object is of a particular type, like a number, string, or a specific class:

function isCar(vehicle: any): vehicle is Car {
 return (
 typeof vehicle === "object" &&
 vehicle !== null &&
 "brand" in vehicle &&
 "model" in vehicle &&
 "year" in vehicle
 );
 }

 interface Car {
 brand: string;
 model: string;
 year: number;
 }

 function inspectVehicle(vehicle: any) {
 if (isCar(vehicle)) {
 // Inside this block, TypeScript knows that 'vehicle' is of type 'Car'
 console.log("Brand:", vehicle.brand);
 console.log("Model:", vehicle.model);
 console.log("Year:", vehicle.year);
 } else {
 console.log("Not a valid car object.");
 }
 }

The code above checks if a given object is of type Car. It includes an interface Car that defines the properties brand, model, and year. It also includes a function inspectVehicle that takes an object as a parameter and checks if it is a Car using the isCar type guard function. If it is a Car, it logs the brand, model, and year of the vehicle. Otherwise, it logs that it is not a valid car object.

We use the inspectVehicle function to check if the vehicle parameter is indeed a Car. If the vehicle is a Car, it logs the brand, model, and year of the vehicle. If the vehicle is not a Car, it logs that it is not a valid car object.

We can test with a car object as seen in the code block below:

const myCar = {
 brand: "Toyota",
 model: "Camry",
 year: 2020
};

inspectVehicle(myCar);

Or test with a non-car object as seen here:

 const myBike = { type: "Mountain Bike", wheels: 2 };
 inspectVehicle(myBike);

Conclusion

TypeScript type guards help assure the value of a type, improving the overall code flow. In this article, we reviewed several of the most helpful type guards in TypeScript, exploring a few examples to see them in action.

Oftentimes, your use case can be solved using either the instanceof type guard, the typeof type guard, or the in type guard. However, you can use a custom type guard when it is necessary.

I hope you enjoyed this article! Be sure to leave a comment if you have any questions.

LogRocket understands everything users do in your web and mobile apps.

πŸ‘ LogRocket Dashboard Free Trial Banner

LogRocket lets you replay user sessions, eliminating guesswork by showing exactly what users experienced. It captures console logs, errors, network requests, and pixel-perfect DOM recordings β€” compatible with all frameworks, and with plugins to log additional context from Redux, Vuex, and @ngrx/store.

With Galileo AI, you can instantly identify and explain user struggles with automated monitoring of your entire product experience.

Modernize how you understand your web and mobile apps β€” start monitoring for free.

πŸ‘ Image
πŸ‘ Image
πŸ‘ Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Debug Next.js apps with AI agents and next-browser

Learn how next-browser gives AI agents runtime context for debugging Next.js apps, including React props, hydration, PPR, forms, and performance.

πŸ‘ Image
Emmanuel John
Jun 17, 2026 β‹… 9 min read

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

πŸ‘ Image
Chizaram Ken
Jun 16, 2026 β‹… 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension β€” no new framework required.

πŸ‘ Image
Ikeh Akinyemi
Jun 12, 2026 β‹… 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo β€” with email/password login, Google OAuth, session persistence, and protected routes.

πŸ‘ Image
Chinwike Maduabuchi
Jun 9, 2026 β‹… 13 min read
View all posts

Hey there, want to help make our blog better?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now