TypeScript는 단순히 타입을 정의하는 언어가 아니라, 타입을 계산하고 결과를 반환하는 언어입니다. 이를 가능하게 하는 핵심 기능이 바로 조건부 타입(Conditional Type)입니다. 조건부 타입은 “특정 타입이 다른 타입에 할당 가능한지”를 기준으로 타입을 분기합니다.
T extends U ? X : Y
즉, T가 U에 할당 가능하면 X, 아니면 Y 타입을 반환하는 형태입니다. 조건부 타입을 활용하면, 복잡한 타입 변환을 자동화하고 확장성 높은 타입 시스템을 구축할 수 있습니다.
기본 문법
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<number>; // false
조건부 타입은 값이 아닌 타입을 대상으로 if-else 연산을 수행한다고 이해하면 쉽습니다.
유니온 타입과 함께 동작
type ToBoolean<T> = T extends string ? true : false;
type C = ToBoolean<string | number>;
// (string → true) | (number → false)
// 결과: true | false
조건부 타입은 유니온 타입에 대해 각각 개별적으로 평가됨에 주의해야 합니다. 이를 “분배적 조건부 타입(Distributive Conditional Types)”이라고 부릅니다.
infer와 함께 사용 - 타입 추출
조건부 타입은 infer 키워드와 결합될 때 가장 강력해집니다.
type Return<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = () => Promise<number>;
type D = Return<Fn>; // Promise<number>
infer를 이용하면 기존 타입 내부에서 특정 타입을 꺼내 자동으로 재사용할 수 있습니다.
조건부 타입 응용 예제
1. Nullable 타입 제거
type NonNull<T> = T extends null | undefined ? never : T;
type E = NonNull<string | null>; // string
2. Promise 내부 타입 추출
type Awaited<T> = T extends Promise<infer R> ? R : T;
type F = Awaited<Promise<number>>; // number
3. 배열/튜플 요소 타입 추출
type Element<T> = T extends (infer U)[] ? U : never;
type G = Element<[number, string]>; // number | string
4. Required를 제거한 Partial 분리
type PickOptional<T> = {
[K in keyof T as {} extends Pick<T, K> ? K : never]: T[K];
};
조건부 타입은 매핑된 타입(Mapped Type)과 함께 쓰면 DTO 변환 자동화가 가능합니다.
분배적 조건부 타입(Distributive Conditional Types)
다음 예시를 통해 확인할 수 있습니다:
type Exclude<T, U> = T extends U ? never : T;
type H = Exclude<string | number | boolean, string>;
// string → never
// number → number
// boolean → boolean
// 결과: number | boolean
유니온 타입의 각 멤버마다 조건이 평가되므로 자동 분해 및 타입 재조합이 가능합니다.
분배를 막는 방법
유니온 타입에서 분배가 원치 않을 때는 타입을 []로 감싸면 됩니다.
type NoDistribute<T> = [T] extends [string] ? true : false;
type I = NoDistribute<string | number>;
// [string | number] extends [string] → false
분배 여부를 의도적으로 제어해야 하는 상황에서 유용합니다.
실무에서 조건부 타입을 사용해야 하는 순간
- API 응답 타입 자동 생성
- Entity → DTO 변환 자동화
- Promise / 함수 / 튜플 / 객체 내부 타입 추출
- 유니온 타입에 따라 타입 분기 처리
- 선택적 필드와 필수 필드를 자동으로 분리
- 제네릭 기반의 라이브러리 구축 시 필수
조건부 타입을 숙달하면 타입 설계의 생산성과 유지보수성이 극적으로 향상됩니다.
조건부 타입은 TypeScript의 고급 타입 시스템을 지탱하는 핵심 기능입니다. 단순 비교를 넘어, infer·Mapped Type·유틸리티 타입과 결합되면서 자동 타입 생성 및 타입 추론 기반 구조 설계를 가능하게 합니다.
- T extends U ? X : Y — 타입 분기
- 유니온에 대해 분배적으로 동작
- infer와 함께 쓰면 타입 추출 가능
- 복잡한 DTO/Entity/API 타입 자동화에 필수
'개발 > Typescript' 카테고리의 다른 글
| [TYPESCRIPT] infer 키워드로 타입 추론하기 — 조건부 타입의 핵심 메커니즘 (0) | 2025.12.14 |
|---|---|
| [TYPESCRIPT] Record, Exclude, Extract, NonNullable 정리 — 실무에서 자주 쓰는 타입 변환 도구 (0) | 2025.12.13 |
| [TYPESCRIPT] Partial, Pick, Omit, Required 유틸리티 타입 활용 — 실무에서 가장 많이 쓰이는 타입 변환 패턴 (0) | 2025.12.12 |
| [TYSCRIPT] 제네릭 제약조건(extends) 사용법 — 타입 안정성을 높이는 핵심 기법 (0) | 2025.12.10 |
| [TYPESCRIPT] 제네릭 함수와 클래스 활용하기 - 재사용성과 타입 안정성을 모두 잡는 방법 (0) | 2025.12.09 |
