타입 가드를 적절하게 사용하여 타입을 좁혀가자
범용성 있는 공통 함수를 구현하기 위해서는 타입 좁히기가 중요하다.
컴파일러에서 제어 흐름 분석을 진행할 시 타입 가드를 마주하게 되면 타입 좁히기가 발생
*대부분의 제어문 을 통해 타입가드를 설정할 수 있다.
const fnc = (arg: string | number) => {
if (typeof arg === 'string') {
// arg > string 타입 추론
} else {
// arg > number 타입 추론
}
}
// 단순히 null 체크의 경우
const fnc = (arg?: string) => {
if (arg) {
// arg > string 타입 추론
} else {
// arg > null 타입 추론
}
}
// thorw를 통해 좁히기 가능
const fnc = (arg?: string) => {
if(!arg) throw new Error('에러 발생!');
// arg > string 타입 추론
}
const fnc = (arg: any) => {
if(typeof arg === 'object') {
// arg > object | null 타입 추론
// null이 object 형태이기 때문에 제외되지 않았다.
}
}
const fnc = (arg: number | string | null) => {
if (!arg) {
// '', 0 === false 이기 때문에 타입 가드가 성립이 안된다.
}
}
interface Guest {
guestId: number;
name: string;
}
interface Admin {
adminId: number;
name: string;
}
const fnc = (user: Guest | Admin) => {
if ('guestId' in user) {
// user > Guest 타입 추론
}
// user > Admin 타입 추론
}
const fnc = (a: number | string, b: number | boolean) => {
if (a === b) {
// a, b 모두 number 타입 추론
}
}
interface Guest {
guestId: number;
name: string;
role: 'guest';
}
interface Admin {
adminId: number;
name: string;
role: 'admin';
}
type User = Guest | Admin;
const fnc = (user: User) => {
switch (user.role) {
case 'guest':
// user > Guest 타입 추론
break
case 'admin':
// user > Admin 타입 추론
break
}
}
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
const isFish = (pet: Fish | Bird): pet is Fish =>
(pet as Fish).swim !== undefined;
if (isFish(pet)) {
// pet > Fish 타입 추론
pet.swim();
}
else {
// pet > Bird 타입 추론
pet.fly();
}
pet is Fish > 함수가 호출된 범위 내에선 pet을 Fish타입으로 보라
is 키워드는 컴파일 단계에서만 사용되며 런타임 단계에서는 순수한 js 파일과 동일하게 동작
- as는 타입 단언으로, 컴파일 단계에서 타입스크립트가 잘못 혹은 보수적으로 타입을 추론하는 경우
개발자가 수동으로 컴파일러에게 특정 변수에 대한 타입 힌트를 주는 것
- is는 타입 가드로, 한정된 범위 내의 모든 변수에 대해서 일괄적으로 적용할 수 있는 키워드
Reference