만약 두 개 이상의 타입을 하나의 조건에 넣으려면 어떻게 해야 할까? 밑의 예제는 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}`
    }
}

Intersection Type

유니언 타입이 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)
}