ReasonJun

Typescript : Type Guard 본문

Frontend/Typescript

Typescript : Type Guard

ReasonJun 2023. 6. 10. 12:10
728x90

In TypeScript, a type guard is a runtime check that allows you to narrow down the type of a value within a conditional block. Type guards enable you to make more precise type inferences based on certain conditions, improving type safety and enabling more expressive and reliable code.

Type guards are particularly useful when working with union types or when the TypeScript compiler cannot determine the specific type of a value through type inference alone. By applying a type guard, you can narrow down the possibilities and operate on the value with confidence.

There are several ways to perform type guards in TypeScript:

  • typeof Type Guards: Using the typeof operator, you can check the type of a value against specific types.
function printLength(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.length); // TypeScript infers `value` as `string`
  } else {
    console.log('Value is not a string.');
  }
}

In this example, the typeof value === 'string' check acts as a type guard that narrows down the type of value to string within the conditional block. TypeScript then allows accessing the length property of the string.

  • instanceof Type Guards: Using the instanceof operator, you can check if a value is an instance of a specific class or constructor function.
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

function greet(person: Person | string) {
  if (person instanceof Person) {
    console.log('Hello, ' + person.name); // TypeScript infers `person` as `Person`
  } else {
    console.log('Hello, ' + person); // TypeScript infers `person` as `string`
  }
}

In this example, the person instanceof Person check acts as a type guard that narrows down the type of person to Person within the conditional block. TypeScript then allows accessing the name property of the Person type.

  • Custom Type Predicates: You can define your own functions that return a boolean value indicating whether a value satisfies certain type conditions. These functions are called type predicates and can be used as type guards.
interface Cat {
  meow(): void;
}

function isCat(pet: any): pet is Cat {
  return typeof pet.meow === 'function';
}

function playWithPet(pet: Cat | Dog) {
  if (isCat(pet)) {
    pet.meow(); // TypeScript infers `pet` as `Cat`
  } else {
    pet.bark(); // TypeScript infers `pet` as `Dog`
  }
}

In this example, the isCat function is a type predicate that checks if a value has a meow method. When isCat(pet) returns true, TypeScript narrows down the type of pet to Cat within the conditional block.

Type guards help you write more reliable and type-safe code by narrowing down types based on runtime checks. They enable you to leverage TypeScript's static type system even when dealing with uncertain or dynamic types. By using type guards effectively, you can enhance code readability, prevent runtime errors, and benefit from improved autocompletion and type checking in your IDE.

// type guard

function logText(el: Element) {
    console.log(el.textContent)
}

const h1El = document.querySelector('h1') as HTMLHeadElement
// Declarate that it is not null and eliminate error.
logText(h1El)

// But the above code generates an error on the web.This is because NULL data is actually entered.

// Solve as follows. (guard)
if (h1El) {
    logText(h1El)
}

// or
if (h1El instanceof HTMLHeadingElement) {
    //If it is not htmlheadingelement, the code below does not run.
    logText(h1El)
}

function addd(val: string | number | boolean) {
    let res = 'Result =>'
    if (typeof val === 'number') {
        res += val.toFixed(2)
    } 
    if (typeof val === 'string') {
        res += val.toUpperCase()
    }
    console.log(res)
}

addd(3.141592) // Result => 3.14
addd('hello world') // Result => HELLO WORLD
728x90
Comments