[Typescript] Type Guard로 타입 좁히기
타입스크립트 Type Guard로 타입 좁히기
Type Guard
컴파일러가 타입을 예측할 수 있도록 타입을 좁혀주어서 타입의 안전함을 보장할 수 있다.
typeof를 사용한 type guards
Javascript의 typeof 연산자를 활용하여 타입가드를 할 수 있다.
const test = (a: number | string) => {
if (typeof a === "string") {
return a.substring(1);
}
return a;
};
함수의 인자로 넘어온 a값은 number이거나 string일 수 있는데
바로 a.substring을 사용하면 number에는 substring을 사용할 수 없기 때문에 에러가 발생한다.
typeof를 사용하여 if문 내에서 a값이 string임을 보장을 시킬 수 있다.
in을 사용한 type guards
Javascript의 in 연산자를 활용하여 객체에 대한 타입가드를 할 수 있다.
type Student = {
name: string;
class: number;
};
type OfficeWorker = {
name: string;
salary: number;
};
type Person = Student | OfficeWorker;
const test = (info:Person) => {
console.log(info.name);
console.log(info.class); // OfficeWorker에는 class가 없기 때문에 에러 발생
if ("class" in info) { // in을 사용하여 TypeGuard 해주면 에러 없이 처리 가능
console.log(info.class);
}
}
instanceof를 사용한 type guards
Javascript의 instanceof 연산자를 활용하여 클래스에 대한 타입가드를 할 수 있다.
class Person {
greet() {
console.log("Hi!");
}
}
class Student {
greet() {
console.log("Hello");
}
myAge(age: number) {
console.log("I'm" + age);
}
}
type User = Person | Student;
const user1 = new Person();
const user2 = new Student();
const test = (user: User) => {
// user.myAge(100); // Person에는 myAge가 없기 때문에 에러 발생
if ("myAge" in user) { // in 사용 가능
user.myAge(100);
}
if (user instanceof Student) { // instanceof 사용 가능
user.myAge(100);
}
};
in으로도 타입가드가 가능하지만 문자열을 작성하는 것 보다는
instanceof를 사용하는 것이 조금 더 안전하다.
특정 프로퍼티를 사용한 type guards
객체 안에 구분할 수 있는 프로퍼티를 넣어 타입가드를 할 수 있다.
interface Student {
type: "student";
name: string;
age: number;
}
interface OfficeWorker {
type: "officeWorker";
name: string;
salary: number;
}
type Person = Student | OfficeWorker;
const test = (person: Person) => {
switch (person.type) {
case "student":
return person.age;
case "officeWorker":
return person.salary;
}
};
interface에 type을 지정해두고 switch문을 통해 타입가드를 할 수 있다.
Person에 유니온 타입을 지정해두었기 때문에 switch문의 case작성란에서 자동 완성이 가능하다.
객체와 유니언 타입을 사용하여 작업할 때 유용한 패턴이라고 한다.
사용자 정의 type guards
사용자 정의 함수를 만들어서 타입가드를 할 수 있다.
const isAge = (arg: any): arg is Student => {
// age 프로퍼티가 있다면 arg의 타입을 Student로 추론한다.
return arg.age !== undefined;
};
const test = (person: Person) => {
if (isAge(person)) {
return person.age;
} else {
return person.salary
}
};
Reference
https://chanhuiseok.github.io/posts/ts-2/
https://www.udemy.com/course/best-typescript-21/learn/lecture/27938024#overview
https://radlohead.gitbook.io/typescript-deep-dive/type-system/typeguard