TypeScript 조건부 흐름

조건부 타입 평가 흐름

T extends U ? X : Y는 단순한 삼항식처럼 보이지만, 제네릭 입력이 유니언인지, 구조에서 타입을 추출하는지, 분산을 막아야 하는지에 따라 결과가 달라진다.

T extends U ? X : Y
1

기본 판정

TU에 할당 가능하면 true 분기 X, 아니면 false 분기 Y로 간다.

T extends string ? "text" : "other"
2

유니언 분산

제네릭 T가 그대로 조건 왼쪽에 있으면 유니언 멤버마다 따로 평가한 뒤 다시 합친다.

Exclude<"a" | "b", "b"> => "a"
3

infer 추출

오른쪽 패턴이 맞을 때 내부 위치의 타입을 임시 이름으로 꺼내 다음 분기에서 쓴다.

T extends Promise<infer R> ? R : T
4

분산 방지

전체 유니언을 한 번에 비교해야 할 때는 양쪽을 튜플로 감싸 분산 평가를 멈춘다.

[T] extends [U] ? X : Y
5

유틸리티 타입

NonNullable, Extract, ReturnType 같은 타입은 이 흐름을 실전 API로 포장한 것이다.

ReturnType<() => number> => number
distribute

멤버별 평가

T extends U에서 T가 naked type parameter이면 A | BA 평가와 B 평가로 나뉜다.

wrap

전체 평가

[T] extends [U]처럼 감싸면 A | B 전체가 하나의 타입으로 비교되어 의도치 않은 필터링을 피할 수 있다.