Hack Frontend Community

What is TypeGuard in TypeScript

TypeGuard is a mechanism in TypeScript that helps narrow a variable's type within a code block. It allows TypeScript to precisely determine a variable's type based on conditions, making code safer and allowing the compiler to better check types.

TypeGuard is used to check a variable's type and narrow its type in a specific context. This is especially useful when a variable can be one of several types and you need to perform actions specific to a particular type.

TypeGuard Working Principle

TypeScript provides several ways to implement TypeGuard, including:

  1. Custom TypeGuard functions.
  2. Type checking operators like typeof and instanceof.
  3. Custom type checks using is.

TypeGuard Usage Examples

  1. Example with typeof:

    The typeof operator allows checking primitive types like string, number, boolean and others. In the case of TypeGuard, this allows narrowing a variable's type in a code block.

    function printLength(value: string | number) {
      if (typeof value === "string") {
        console.log(value.length);  // Works since value is definitely string
      } else {
        console.log(value.toFixed(2)); // Works since value is definitely number
      }
    }
    
    printLength("Hello");  // Output: 5
    printLength(42);       // Output: 42.00
    

    In this example, the typeof operator allows TypeScript to understand that in the if block the value variable is a string, and in the else block — a number.

  2. Example with instanceof:

    The instanceof operator is used to check object types, for example, classes. This allows precisely determining an object's type if it's an instance of some class.

    class Dog {
      bark() {
        console.log("Woof!");
      }
    }
    
    class Cat {
      meow() {
        console.log("Meow!");
      }
    }
    
    function speak(animal: Dog | Cat) {
      if (animal instanceof Dog) {
        animal.bark();  // Access to bark method since animal is Dog
      } else {
        animal.meow();  // Access to meow method since animal is Cat
      }
    }
    
    const dog = new Dog();
    const cat = new Cat();
    
    speak(dog);  // Output: Woof!
    speak(cat);  // Output: Meow!
    
  3. Custom TypeGuard functions

    You can create your own functions for type checking and using TypeGuard with the is keyword.

    type Dog = { bark: () => void };
    type Cat = { meow: () => void };
    
    function isDog(animal: Dog | Cat): animal is Dog {
      return (animal as Dog).bark !== undefined;
    }
    
    function speak(animal: Dog | Cat) {
      if (isDog(animal)) {
        animal.bark();  // animal is now definitely type `Dog`
      } else {
        animal.meow();  // animal is now definitely type `Cat`
      }
    }
    
    const dog: Dog = { bark: () => console.log("Woof!") };
    const cat: Cat = { meow: () => console.log("Meow!") };
    
    speak(dog);  // Output: Woof!
    speak(cat);  // Output: Meow!
    

Why use TypeGuard?

  • Type safety: TypeGuard helps avoid errors related to incorrect variable usage, as TypeScript precisely understands which variable type is used in each code block.

  • Improved code readability: Using TypeGuard makes code more understandable and predictable, as it explicitly indicates which data types are processed in each block.

  • Better code understanding for IDE: TypeScript and IDEs (e.g., Visual Studio Code) can use TypeGuard to improve hints, autocomplete and refactoring, speeding up development and improving code work.