조건문에서 객체의 타입을 좁혀나가는 방법이다.
👇 예제 코드를 살펴보자.
const typeGaurd : string | number = "무슨 타입일까?"
typeGaurd는 string, number 둘 중 하나의 타입만을 가지면 된다.
function whatType(typeGaurd: string | number) {
// string, number 둘 중 어떤 것이 올지 알 수 없다.
}
하지만, 위와 같은 함수가 존재할 때 인자는 2개의 타입을 가지고 있기 때문에 어느 타입을 가지고 있을지 알 수 없다.
이렇게 해당 타입에 대한 확신과 검증이 필요할 때 사용하는 것이 타입 가드이다.
typeof를 사용하여 해당 조건문 블록 내에서 해당 변수의 타입이 다르다는 것을 인식하도록 한다.
👇 typeof 연산자를 통해 인자로 들어온 typeGaurd의 타입을 확인하는 예제 코드이다.
function typeofDecision(typeGaurd: string | number) {
if(typeof typeGaurd === 'string'){
typeGaurd.substr(0);
}else{
Math.floor(typeGaurd);
}
}
string 타입일 경우와 number 타입에 따라서 사용할 수 있는 메소드가 다르므로 좁혀진 범위의 타입을 검사하였다.
Class를 사용하는 경우 typeof 연산자로는 항상 object를 얻게 되므로 instanceof를 사용해야 한다.
class Top {
top = "shirts";
quantity= 12;
}
class Bottom {
bottom = "Skirt";
quantity = 2;
}
function dressUp(kind: Top | Bottom) {
console.log(typeof kind); // object
if (kind instanceof Top) {
console.log(kind.top);
}
if (kind instanceof Bottom) {
console.log(kind.bottom);
}
console.log(kind.quantity);
console.log(kind.top); // Error!
console.log(kind.bottom); // Error!
// 'Top | Bottom' 형식에 'top' 속성이 없습니다.
}
dressUp(new Top());
/* shirts
12
*/
dressUp(new Bottom());
/* Skirt
2
*/
kind에 대해 typeof로 접근하면 object를 출력함을 알 수 있다.
타입 좁히기를 위해서 instanceof를 사용하고, 각각의 타입에 대한 출력을 다르게 수행하여 오류를 방지해야 한다.
여기서!!
if (kind instanceof Top) {
console.log(kind.top);
} else {
// 반드시 Bottom이다.
console.log(kind.bottom);
}
또 다른 if가 아닌 else로 조건문을 구현하면 앞선 if의 타입이 아닌 타입으로 반드시 지정된다.
in 키워드를 통해 객체 내부에 특정 property가 존재하는지 검사한다.
👇 프로퍼티를 비교하기에 더 정밀한 타입 좁히기가 가능하다.
interface Top {
top: string;
}
interface Bottom {
bottom: string;
}
function dressUp(kind: Top | Bottom) {
if ("top" in kind) {
console.log(kind.top);
} else {
console.log(kind.bottom);
}
}
dressUp({top : "셔츠"}) // 셔츠
dressUp({bottom : "치마"}) // 치마
JavaScript 언어는 풍부한 런타임 내부 검사를 지원하지 않는다.
일반 JavaScript 객체(구조적 타입 structural typings 활용)를 사용할 때에는 instanceof나 typeof와 같은 연산자에 접근하는 것도 불가능하다.
하지만 TypeScript에서는 사용자 정의 Type Guard 함수를 만들어 이를 해결할 수 있다.
👇 value is Type 형태
의 반환 타입을 갖는 함수로 정의하여 사용한다.
interface Top {
top: string;
}
interface Bottom {
bottom: string;
}
function isTop(kind: any ): kind is Top {
return kind.top !== undefined;
}
function dressUp(kind: Top | Bottom) {
if (isTop(kind)) {
console.log(kind.top);
} else {
console.log(kind.bottom);
}
}
dressUp({top : "셔츠"}) // 셔츠
dressUp({bottom : "치마"}) // 치마
📚 학습할 때, 참고한 자료 📚