만약 두 개 이상의 타입을 하나의 조건에 넣으려면 어떻게 해야 할까? 밑의 예제는 padding에 number나 string 두 개의 타입을 허용하고 싶을 때, 방법이 없어 any로 일단 설정한 코드이다.
function padLeft(value: string, padding: **any**): string {...};
let indentedString = padLeft("Hello world", **true**)
이렇게 사용을 하면, 컴파일 단계(타입스크립트 → 자바스크립트)에서는 문제가 발생하지 않겠지만, 이 함수를 실행하는 런타임 단계에서는 에러가 발생할 것이다. 이보다는 유니언을 사용하여 간결하게 표현할 수 있다.
function padLeft(value: string, padding: number | string): string {...};
이는 or(|
)를 사이에 둔 타입들 중 하나만을 가진다는 뜻이므로, 유니언 타입에 선언된 여러 타입들을 동시에 받을 수는 없다.
type NetworkLoadingState = {
state: 'loading'; // 리터럴 타입
}
type NetworkFailedState = {
state: 'failed';
code: number;
}
type NetworkSuccessState = {
state: "success";
response: {
title: string;
duration: number;
summary: string;
}
}
type NetworkState =
NetworkLoadingState
| NetworkFailedState
| NetworkSuccessState
위와 같이 네트워크 상태에 대한 타입을 만들었다고 가정해보자.
이 때 밑과 같이 해당 타입을 사용할 때, 분기문을 사용해서 해당 유니언 타입을 좁혀나갈 수 있다!
function networkStatus(state: NetworkState): string {
state.code; // 오류. 지금 상태에서는 state가 어떤 타입인지 알 수 없다.
// 타입 안의 리터럴 타입을 사용한 분기문으로 타입을 좁혀 나갈 수 있다.
switch (state.state) {
case "loading":
return "Downloading..."
case "failed":
return `Error ${state.code} downloading`
case "success":
return `Downloaded ${state.response.title} : ${state.response.summary}`
}
}
유니언 타입이 or를 사용하여 여러 타입 중 하나의 타입을 사용할 수 있도록 했다면, intersection type은 여러 개의 타입을 하나로 결합해 사용할 수 있는 방식이다.
ArtworksData와 ArtistsData에 ErrorHandling이라는 공통 타입을 intersection type을 통해 붙였다!
interface ErrorHandling {
success: boolean;
error?: {message: string};
}
interface ArtworksData {
artworks: {title: string}[];
}
interface ArtistsData {
artists: {name: string}[];
}
type ArtworksResponse = ArtworksData **& ErrorHandling**
type ArtistsResponse = ArtistsData **& ErrorHandling**
const handleArtistsResponse = (res: ArtistsResponse) => {
if(res.error) {
console.error(res.error.message)
return
}
console.log(res.artists)
}