type guard
를 통해 컴파일러가 타입을 예측할 수 있도록 타입을 좁혀주어 (narrowing) 좀 더 type safety
를 보장할 수 있다.
리터럴은 ===
, !==
연산자를 이용해 타입을 구분할 수 있다.
type B = { type: "b"; bbb: string };
type C = { type: "c"; ccc: string };
type D = { type: "d"; ddd: string };
function typeCheck(a: B | C | D) {
if (a.type === 'b') {
a.bbb
} else if (a.type === 'c') {
a.ccc
} else {
a.ddd
}
}
조건문 블록에 typeof
를 사용하여 변수의 타입을 좁힐 수 있다.
function doSomething(x: number | string) {
if (typeof x === 'string') { // TypeScript는 이 조건문 블록 안에 있는 `x`는 백퍼 `string`이란 걸 알고 있습니다.
console.log(x.subtr(1)); // Error: `subtr`은 `string`에 존재하지 않는 메소드입니다.
console.log(x.substr(1)); // ㅇㅋ
}
x.substr(1); // Error: `x`가 `string`이라는 보장이 없죠.
}
class의 instanceof를 이용할 수도 있다
class Foo {
foo = 123
}
class Bar {
bar = 333
}
function doStuff (arg : Foo | Bar) {
if (arg instanceof Foo) {
arg.foo
} else if (arg instanceof Bar) {
arg.bar
}
}
in은 객체 내부에 특정 프로퍼티가 존재하는지 연산자로 확인할 수 있다
interface A {
x: number;
}
interface B {
y: string;
}
function doStuff(q: A | B) {
if ('x' in q) {
q.x
}
else {
q.y
}
}