interface Apple { isGoodForBaking: boolean; }
interface Orange { numSlices: number; }
function pickFruit(fruit: Apple | Orange) {
if ('isGoodForBaking' in fruit) {
fruit
// ^? (parameter) fruit: Apple
} else {
fruit
// ^? (parameter) fruit: Orange
}
fruit
// ^? (parameter) fruit: Apple | Orange
}
이 패턴은 '태그된 유니온' 또는 '구별된 유니온'이라고 불리며, 타입스크립트 어디서나 찾아볼 수 있다.
⭐️ 커스텀 함수 도입
타입스크립트가 타입을 식별하지 못한다면, 식별을 돕기 위해 커스텀 함수를 도입한다.
function isInputElement(el: Element): el is HTMLInputElement {
return 'value' in el;
}
function getElementContent(el: HTMLElement) {
if (isInputElement(el)) {
return el.value;
// ^? (parameter) el: HTMLInputElement
}
return el.textContent;
// ^? (parameter) el: HTMLElement
}
'사용자 정의 타입 가드' 라고 한다. 반환 타입의 el is HTMLInputElement는 함수의 반환이 true인 경우, 타입 체커에게 매개변수의 타입을 좁힐 수 있다고 알려준다.
⭐️ 타입 가드 사용
타입 가드를 사용하여 배열과 객체의 타입 좁히기를 할 수 있다.
배열에서 어떤 탐색을 수행할 때 undefined가 될 수 있는 타입을 사용할 수 있다.
const jackson5 = ['Jackie', 'Tito', 'Jermaine', 'Marlon', 'Michael'];
const members = ['Janet', 'Michael'].map(
who => jackson5.find => n === who)
); // 타입이 (string|undefined)[]
filter 함수를 사용해 undefined를 걸러내려고 해도 잘 동작하지 않는다. 이럴 때 타입 가드를 사용하면 타입을 좁힐 수 있다.
function isDefined<T>(x: T | undefined): x is T {
return x !== undefined;
}
const members = ['Janet', 'Michael'].map(
who => jackson5.find => n === who)
).filter(isDefined); // 타입이 string[]
📍 정리
편집기에서 타입을 조사하는 습관을 가지면 타입 좁히기가 어떻게 동작하는지 익힐 수 있다. 타입이 좁혀지는 과정을 이해한다면 타입 추론에 대한 개념을 잡을 수 있고, 오류 발생의 원인을 알 수 있으며, 타입 체커를 더 효율적으로 이용할 수 있다.
📍 요약
분기문 외에도 여러 종류의 제어 흐름을 살펴보며 타입스크립트가 타입을 좁히는 과정을 이해하자.
태그된/구별된 유니온과 사용자 정의 타입 가드를 사용하여 타입 좁히기 과정을 원활하게 만들 수 있다.