Typescript Foundations / Advanced Types

Type Guards: typeOf, instaceOf, custom

A type guard is a runtime check that narrows the type of a variable within a conditional block.

Without type guards, TypeScript might not know the exact type and will raise an error if you try to access a type-specific property or method.


✅ typeof Type Guard

Use typeof to check primitive types like "string", "number", "boolean", etc.

📌 Syntax

function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());  // ✅ string methods available
  } else {
    console.log(value.toFixed(2));     // ✅ number methods available
  }
}

✅ Valid typeof checks:

  • "string"

  • "number"

  • "boolean"

  • "undefined"

  • "symbol"

  • "bigint"

  • "function"

  • "object"


✅ instanceof Type Guard

Used to check class-based objects.

class Car {
  drive() {
    console.log("Driving...");
  }
}

class Boat {
  sail() {
    console.log("Sailing...");
  }
}

function operate(vehicle: Car | Boat) {
  if (vehicle instanceof Car) {
    vehicle.drive();  // ✅ TypeScript now knows it's a Car
  } else {
    vehicle.sail();   // ✅ It's a Boat here
  }
}

✅ Best for checking custom classes (not interfaces).


✅ Custom Type Guards (User-Defined)

Write your own type guard function using a return type like:

value is SomeType

🧠 Example:

type Dog = { kind: "dog"; bark: () => void };
type Cat = { kind: "cat"; meow: () => void };
type Animal = Dog | Cat;

function isDog(animal: Animal): animal is Dog {
  return animal.kind === "dog";
}

function makeSound(animal: Animal) {
  if (isDog(animal)) {
    animal.bark();       // ✅ Safe to call
  } else {
    animal.meow();       // ✅ It's a cat
  }
}

🔍 Another Example with Property Checks:

function isStringArray(input: unknown): input is string[] {
  return Array.isArray(input) && input.every(item => typeof item === "string");
}

🧪 Bonus: in Operator

Used to check if a property exists in an object.

type Admin = { role: "admin"; level: number };
type User = { role: "user"; access: string };

type Person = Admin | User;

function showDetails(person: Person) {
  if ("level" in person) {
    console.log(`Admin Level: ${person.level}`);
  } else {
    console.log(`User Access: ${person.access}`);
  }
}


🧠 Summary

Type Guard

Works With

Example

typeof

Primitives

typeof value === "string"

instanceof

Classes

value instanceof Car

Custom function

Any type (with logic)

isDog(animal): animal is Dog

in

Properties in objects

"level" in person