Published on

타입단언(Type Assertion)과 타입가드(Type Guard)

Type Assertion

  • 타입 단언(Type Assertion)은 프로그래머가 수동적으로 컴파일러에게 특정변수에 대해 타입 힌트를 주는 것이다.
  • 아래 코드는 컴파일 에러를 낸다. Character 클래스에는 fireBall, attack 메소드가 선언조차 되어있지 않기 때문이다.
    하지만 프로그래머 입장에서 바라보면 isWizard라는 메소드를 통해 확실히 그 캐릭터가 Wizard 인스턴스라는 걸 보장할 수 있다면, if 블록 안에서는 fireBall이라는 메소드를 사용할 수 있어야 한다.
class Character {
  hp: number = 100;
  runAway() {
    /* ... */
  }
  isWizard() {
    /* ... */
  }
  isWarrior() {
    /* ... */
  }
}

class Wizard extends Character {
  fireBall() {
    /* ... */
  }
}

class Warrior extends Character {
  attack() {
    /* ... */
  }
}

function battle(character: Character) {
  if (character.isWizard()) {
    character.fireBall(); // ERROR: Property 'fireBall' does not exist on type 'Character'.
  } else if (character.isWarrior()) {
    character.attack(); // ERROR: Property 'attack' does not exist on type 'Character'.
  } else {
    character.runAway();
  }
}
  • 위의 컴파일 에러를 타입단언을 통해 수정할 수 있다.
function battle(character: Character) {
  if (character.isWizard()) {
    (character as Wizard).fireBall(); // or (<Wizard>character).fireBall()
  } else if (character.isWarrior()) {
    (character as Warrior).attack(); // or (<Warrior>character).attack();
  } else {
    character.runAway();
  }
}
  • 하지만 타입단언을 많이 사용할수록 Typescript를 사용해서 얻는 장점이 점차 사라지기 때문에 가능한 적게 주의해서 사용해야 한다.

Type Guard

  • 타입 가드는 타입 단언을 좀 더 깔끔하게 할 수 있도록 도와준다.
    앞의 예제에서 isWizard라는 메소드로 해당 인스턴스가 해당 타입이라는 사실을 확정했다.
    하지만 이건 런타임에서만 알 수 있는 사실이고 TypeScript 컴파일러는 알 수 없었다.
    타입 가드는 이러한 런타임에서의 타입 체크를 컴파일러에게 알려주는 기능이다.
    아래와 같이 런타임에서 실제 타입검사를 하는 메소드의 리턴타입으로 {variable} is {Type} 문법을 사용해 선언해주면 된다.
class Character {
  isWizard(): this is Wizard {
    return this instanceof Wizard;
  }
  isWarrior(): this is Warrior {
    return this instanceof Warrior;
  }
}

참조