Skip to main content

What is a "type guard"?

What a Type Guard is

A type guard is a logical expression or function that helps TypeScript refine the type of a variable in a particular branch of code.

Put simply: a type guard is a way to "tell the compiler who I really am".


Example without a type guard

javascript
function printId(id: string | number) { console.log(id.toUpperCase()); // Error - id might be a number }

TypeScript doesn't know whether id is a string or a number.


With a Type Guard

javascript
function printId(id: string | number) { if (typeof id === "string") { // here id: string console.log(id.toUpperCase()); } else { // here id: number console.log(id.toFixed(2)); } }

The check typeof id === "string" is a built-in type guard. TS automatically narrows the type inside each branch.


Main kinds of Type Guards

KindCheckExample
typeoffor primitivestypeof value === "string"
instanceoffor classes and constructorsvalue instanceof Date
inchecking whether a property exists"prop" in obj
A custom v is Type functiona custom type guardisString(value): value is string

1. A type guard via typeof

Used to check primitive types: "string", "number", "boolean", "symbol", "undefined", "object", "function".

javascript
function process(val: string | number | boolean) { if (typeof val === "string") { // val: string console.log(val.toUpperCase()); } else if (typeof val === "number") { // val: number console.log(val.toFixed(2)); } else { // val: boolean console.log(val ? "true" : "false"); } }

2. A type guard via instanceof

Used to check whether an object was created by a specific class or constructor.

javascript
function logDate(value: Date | string) { if (value instanceof Date) { // value: Date console.log(value.toISOString()); } else { // value: string console.log(value.toUpperCase()); } }

3. A type guard via the in operator

Checks whether an object has a specific property, and TS narrows the type depending on the result.

javascript
type Car = { drive: () => void }; type Boat = { sail: () => void }; function move(vehicle: Car | Boat) { if ("drive" in vehicle) { // vehicle: Car vehicle.drive(); } else { // vehicle: Boat vehicle.sail(); } }

4. Custom type guards (v is Type)

You can declare your own function that returns a boolean and tells TypeScript that if it returns true, the argument has a specific type.

Syntax:

javascript
function isDog(pet: Animal): pet is Dog { return (pet as Dog).bark !== undefined; }

Usage example:

javascript
type Dog = { bark: () => void }; type Cat = { meow: () => void }; function isDog(animal: Dog | Cat): animal is Dog { return (animal as Dog).bark !== undefined; } function makeSound(animal: Dog | Cat) { if (isDog(animal)) { animal.bark(); // animal: Dog } else { animal.meow(); // animal: Cat } }

Here the expression animal is Dog tells TS: "If the function returned true, then animal is definitely a Dog from here on".


Type guards and narrowing

Type guards are the main mechanism through which type narrowing happens. In effect:

Type guard → triggers narrowing.


An advanced example

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function isCircle(s: Shape): s is { kind: "circle"; radius: number } { return s.kind === "circle"; } function area(shape: Shape) { if (isCircle(shape)) { // shape: circle return Math.PI * shape.radius ** 2; } else { // shape: square return shape.side ** 2; } }

Real-world use cases

  • Validating data after parsing JSON
  • Checking API responses (runtime type checking)
  • Filtering arrays by type
  • Working with union types and discriminated unions
  • Narrowing when working with unknown and any

Example: filtering an array

javascript
function isString(value: unknown): value is string { return typeof value === "string"; } const mixed = [1, "a", 2, "b", true]; const strings = mixed.filter(isString); // strings: string[]

Summary

TermDefinition
Type GuardA check that helps TypeScript determine the specific type of a value
GoalNarrowing union or unknown types
Kindstypeof, instanceof, in, custom (value is Type)
Main benefitSafe access to properties and methods of specific types without casts (as)

Put simply:

A Type Guard is a "guard" that stands in the path of a union type and tells TypeScript: "Don't worry, I checked, now we know exactly who this is".

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.