어떤 함수의 매개변수가 유니온 타입일 때, 합수의 결과 값을 미리 지정할 수가 없다. 매개변수의 타입에 따라 결과값도 달라지기 때문이다.
그러므로 if문으로 타입을 좁히는타입 좁히기(type narrowing)
가 필요하다.
먼저 typeof
연산자를 사용해서 매개변수의 타입을 판별하는 방법이 있다.
function triple(value: number | string) {
if (typeof value === "string") {
return value.repeat(3);
}
return value * 3;
}
위의 코드처럼 매개변수가 string
타입인 경우 ,타입스크립트가 문자로 인식해 문자열에 사용할 수 있는 메서드(repeat
)를 사용할 수 있도록 허용해준다.
그렇지 않은 경우(숫자인 경우) 결과값도 숫자로 반환된다.
만약 매개변수의 타입이 어떤 자료형과 null
(또는 undefined
)라면 Truthiness
로 판별할 수 있다.
const printletters = (word?: string) => {
if (word) {
for (let char of word) {
console.log(char);
}
} else {
console.log("문자를 전달하지 않음!");
}
};
예를 들어 위와 같이 word
가 존재하거나 존재하지 않는 경우를 나눠서 타입 좁히기를 하면 된다.
두 매개변수가 같은 자료형을 가질 수 있는 경우, ===
(일치 연산자, 삼중 동호)를 사용해서 타입 좁히기를 할 수 있다.
function someDemo(x: string | number, y: string | boolean) {
if (x === y) {
x.toUpperCase();
}
}
someDemo(3, "3");
x와 y가 같은 자료형, 즉 string
인 경우에는 결과값으로도 문자열을 반환한다.
위 코드에서처럼 toUpperCase
와 같은 문자열에만 적용할 수 있는 메서드를 사용해도 에러가 발생하지 않는다.
다만 ==
(동등 연산자, 이중 등호, equal operator)로 변경 시 다음과 같은 에러가 발생한다. 타입스크립트가 자료형을 구분하지 못하기 떄문이다.
index.js:30 Uncaught TypeError: x.toUpperCase is not a function
at someDemo (index.js:30:11)
at index.js:33:1
어떤 함수가 매개변수가 2개 이상의 인터페이스를 유니온 타입으로 가질 때,
interface Movie {
title: string;
duration: number;
}
interface TVShow {
title: string;
numEpisodes: number;
episodeDuraiton: number;
}
타입 좁히기를 하려면 in 연산자를 사용한다.
(typeof 연산자를 사용하면 똑같이 객체가 반환되기 때문)
function getRuntime(media: Movie | TVShow) {
if ("numEpisodes" in media) {
return media.numEpisodes * media.episodeDuraiton;
}
return media.duration;
}
위와 같이 만약 매개변수에 numEpisodes
가 있다고 가정하면 해당 매개변수의 인터페이스는 TVShow
일 것이고, 그렇지 않으면 Movie
라는 걸 타입스크립트가 알 수 있다.
console.log(getRuntime({ title: "Amadeus", duration: 140 }));
console.log(
getRuntime({ title: "Spongebob", numEpisodes: 90, episodeDuraiton: 30 })
);
콘솔에 찍어보면 첫 번째 줄은 Movie
인터페이스에 근거해서 media.duration
를 반환하고,
두 번째 줄은 TVShow
인터페이스에 근거해서 media.numEpisodes * media.episodeDuraiton
를 반환한다.
매개변수가 특정 클래스에 속하는지 확인하는 instanceof
연산자를 사용하는 방법이다.
function printFullDate(date: string | Date) {
if (date instanceof Date) {
console.log(date.toUTCString());
} else {
console.log(new Date(date).toUTCString());
}
}
class User {
constructor(public username: string) {}
}
class Company {
constructor(public name: string) {}
}
function printName(entity: User | Company) {
if ("username" in entity) {
entity;
} else {
entity;
}
}