개발 알다가도 모르겠네요

타입스크립트의 타입 추론 본문

웹/Typescript

타입스크립트의 타입 추론

이재빵 2022. 6. 19. 19:18
728x90
let bool = true;
const arr = [1, 2, 3];
const tuple = [true, 1];
bool = 1; // Error!

아래의 tuple 변수는 배열의 요소가 각각 boolean과 number이기에 최종적으로 추론되는 타입은 boolean과 number의 유니온 타입의 배열, 코드로 나타내면 (boolean | number)[]이 됩니다.

여기에서 배열에서 사용된 요소들의 타입을 각각 추론하여 유니온 타입으로 만들어 내는 방식을 Best common type이라고 부릅니다.

 

Best common type

Best common type 은 말 그대로 가장 일반적인 타입입니다.

여러가지 자료형이 배열 내부에서 사용되고 있을 때, 그 여러가지 자료형을 포괄할 수 있는 가장 일반적인 자료형을 추론하는 것입니다.

그 결과로 위의 예제에서는 true와 1을 포괄할 수 있는 자료형인, (boolean | number)가 추론된 것입니다.

class Parent {
  foo = '';
}

class Child extends Parent {
  bar = '';
}

const arr = [new Parent(), new Child()];

 

타입 단언(Type Assertion)

타입 단언은 TypeScript 컴파일러가 타입을 실제 런타임에 존재할 변수의 타입과 다르게 추론하거나 너무 보수적으로 추론하는 경우에 프로그래머가 수동으로 컴파일러한테 특정 변수에 대해 타입 힌트를 주는 것입니다.

class Character {
  hp: number;
  runAway() {
    /* ... */
  }
  isWizard() {
    /* ... */
  }
  isWarrior() {
    /* ... */
  }
}

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

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

function battle(character: Character) {
  if (character.isWizard()) {
    character.fireBall(); // Property 'fireBall' does not exist on type 'Character'.
  } else if (character.isWarrior()) {
    character.attack(); // Property 'attack' does not exist on type 'Character'.
  } else {
    character.runAway();
  }
}

 

이 코드는 컴파일 에러를 내는데 Character 클래스에는 fireBall, attack 메소드가 선언조차 되어있지 않기 때문입니다.

타입 단언으로 적절한 타입을 다시 선언해주면,

function battle(character: Character) {
  if (character.isWizard()) {
    (character as Wizard).fireBall(); // Pass
  } else if (character.isWarrior()) {
    (character as Warrior).attack(); // Pass
  } else {
    character.runAway();
  }
}

해당 변수가 실제로 Wizard 인스턴스가 아니더라도 as 키워드를 통해서 타입 단언을 해줄 수 있기 때문에, 타입 단언은 주의해서 사용해야 합니다.

실제로도 as any 라는 치트키로 대부분의 컴파일 에러를 해결할 수 있지만 as와 any는 가능한 적게 사용하는 것이 좋습니다.

 

 

<Type> vs as Type

타입 단언 문법은 <Type>  as Type 으로 두 종류가 있습니다.

(<Wizard>character).fireBall();
(character as Wizard).fireBall();

그냥 보기에는 <Type> 키워드가 좀 더 깔끔해보이지만, 대개 as Type 키워드가 추천됩니다.

React에서 JSX 를 사용하는 경우 <Type> 키워드는 JSX 의 문법과 겹치기 때문에 불편한 면이 있기 때문입니다.

 

 

타입 가드(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;
  }
}

' > Typescript' 카테고리의 다른 글

타입스크립트의 Type Alias  (0) 2022.06.28
타입스크립트의 타입 가드  (0) 2022.06.27
타입스크립트의 Enum  (0) 2022.06.19
타입스크립트의 함수  (0) 2022.06.18
타입스크립트의 인터페이스  (0) 2022.06.18