1. 개요
특정 scope
내 변수의 타입을 구체적으로 좁힐 수 있도록 해주는 기법이다.
예를 들어 함수의 인자로 여러 타입의 값이 들어올 수 있을 때, type guard
를 이용하면 타입에 따른 적절한 로직을 실행할 수 있다.
const foo = (n: number | string) => {
if (typeof n === "number") {
// number logic
} else {
// string logic
}
};
2. 방법
앞서 코드로 살펴본 typeof
뿐만 아니라 in
혹은 instanceof
키워드를 통해서도 type guard
를 할 수 있다.
class Dog {}
class Cat {}
const foo = (animal: Dog | Cat) => {
if (animal instanceof Cat) {
//
} else {
//
}
};
TypeScript는 결국 JavaScript로 변환되어 실행되기 때문에, type guard
를 하기 위한 조건문 내 로직이 TypeScript에서만 존재하는 문법으로 이루어져있다면, JavaScript로 변환할 수 없기 때문에 에러가 발생한다는 점을 알아야 한다.
예를 들어 interface
키워드는 TypeScript에서만 존재하는 개념이기 때문에 JavaScript로 변환할 수 없다.
따라서 interface
로 선언된 타입을 조건문 내에서 사용할 수 없다.
(interface가 아니라 type으로 선언되었어도 같은 오류가 발생한다)
interface Cat {}
interface Dog {}
const foo = (animal: Cat | Dog) => {
if (animal instanceof Cat) { // 'Cat' only refers to a type, but is being used as a value here.
//
} else {
//
}
};
3. 구별된 유니온 (Discriminated Union)
위와 같은 문제를 해결하기 위한 방법으로 discriminated union
을 쓸 수 있다.
각각의 interface
를 구분할 수 있는 프로퍼티를 제공함으로써 type guard
를 할 수 있다.
interface Cat {
type: "cat";
}
interface Dog {
type: "dog";
}
const foo = (animal: Cat | Dog) => {
if (animal.type === "cat") {
//
} else {
//
}
};