분산적인 조건부 타입
type StringNumberSwitch<T> = T extends number ? string : number;
let a: StringNumberSwitch<number>; // string
let b: StringNumberSwitch<string>; // number
위 조건부 타입에 Union을 할당해 보자.
let c: StringNumberSwitch<number | string>; // string | number
number | string은 number의 서브타입이 아니므로 number가 될 것 같지만, 실제로는 string | number가 된다.
동작 원리
조건부 타입의 타입 변수에 Union 타입을 할당하면 분산적인 조건부 타입으로 동작한다.
1단계: Union 타입 분리
StringNumberSwitch<number | string>은 다음과 같이 분리된다.
StringNumberSwitch<number>StringNumberSwitch<string>
2단계: 각각 계산
StringNumberSwitch<number>→stringStringNumberSwitch<string>→number
3단계: Union으로 결합
string | number
더 복잡한 예시를 보자.
let d: StringNumberSwitch<boolean | number | string>;
// 1단계: 분리
// StringNumberSwitch<boolean> | StringNumberSwitch<number> | StringNumberSwitch<string>
// 2단계: 계산
// number | string | number
// 3단계: 결합
// number | string
Exclude 타입 구현
분산적인 조건부 타입을 활용해 Union 타입에서 특정 타입을 제거하는 Exclude 타입을 만들 수 있다.
type Exclude<T, U> = T extends U ? never : T;
type A = Exclude<number | string | boolean, string>;
동작 원리
1단계: Union 타입 분리
Exclude<number, string>Exclude<string, string>Exclude<boolean, string>
2단계: 각각 계산
number extends string→ 거짓 →numberstring extends string→ 참 →neverboolean extends string→ 거짓 →boolean
3단계: Union으로 결합
number | never | boolean
never는 공집합이므로 Union에서 사라진다. 최종 결과는 number | boolean이다.

Extract 타입 구현
반대로 특정 타입만 추출하는 Extract 타입도 만들 수 있다.
type Extract<T, U> = T extends U ? T : never;
type B = Extract<number | string | boolean, string>; // string

분산 방지하기
분산을 막고 싶다면 extends 양쪽에 대괄호를 씌운다.
type StringNumberSwitch<T> = [T] extends [number] ? string : number;
let d: StringNumberSwitch<boolean | number | string>; // number
[boolean | number | string]은 [number]의 서브타입이 아니므로 분산 없이 조건식이 거짓이 되어 number가 된다.
'TIL' 카테고리의 다른 글
| [TS] 조건부 타입과 infer를 활용한 타입 추론 연습 (0) | 2025.11.05 |
|---|---|
| [TS] infer (타입 추론) (0) | 2025.11.05 |
| [TS] 타입 조작 및 고급 타입 활용 연습 (0) | 2025.11.05 |
| [TS] 템플릿 리터럴 타입 (0) | 2025.11.05 |
| [TS] 맵드 타입 (0) | 2025.11.05 |
