type Dog = {
name: string;
age: number;
};
type PendingState = {
dogName: string;
};
type FulfilledState = {
dog: Dog;
};
type RejectedState = {
dogName: string;
};
type State = PendingState | FulfilledState | RejectedState;
네트워크로 부터의 응답에 대한 상태를 타입으로 표현해보았습니다. 그럼 State
타입의 값이 주어질 때 이것이 Pending인지, Fulfilled인지, Rejected인지는 어떻게 구분할 수 있을까요?
function processState(state: State) {
if ('dogName' in state) {
state; // PendingState | RejectedState
}
else if ('dog' in state) {
state; // FulfilledState
}
}
각 타입만이 가지는 고유한 속성이 있는지 확인하여 Type Narrowing을 해야 합니다.
하지만 PendingState
와 RejectedState
는 동일한 속성을 가지고 있기 때문에 pending
인지, rejected
인지 확인할 수 없습니다.
만약 State
에 다른 타입이 Union으로 추가되었을 때, 기존의 속성과 공통되지 않을 것이라는 보장이 있을까요?
Discriminated Unions
Tagged Unions 라고도 합니다
구분 가능한 유니온 으로 해석할 수 있습니다.
간단히 설명하자면 유니온을 구분하기 위한 필드를 추가하는 것입니다.
type Dog = {
name: string;
age: number;
};
type PendingState = {
type: "pending";
dogName: string;
};
type FulfilledState = {
type: "fulfilled";
dog: Dog;
};
type RejectedState = {
type: "rejected";
dogName: string;
};
type State = PendingState | FulfilledState | RejectedState;
각 상태에 type
이라는 필드를 추가하고 String Literal Type을 넣어주었습니다. 만약 PendingState
로 Type Narrowing을 한다면, state.type === 'pending'
으로 Narrowing할 수 있습니다.
function processState(state: State) {
if (state.type === "pending") {
state; // PendingState
} else if (state.type === "fulfilled") {
state; // FulfilledState
} else if (state.type === "rejected") {
state; // FulfilledState
}
}
유니온의 각 타입을 구분하는 type
이라는 프로퍼티만 서로 다르게 가지면 되기 때문에, 서로 중복될 일도 없을 것입니다.