📚 타입스크립트 입문 시리즈
🟢 ① tsconfig.json 완전 정복 | 🟢 ② 개발 환경 세팅 | 🟢 ③ 기본 타입 정복 | 🟢 ④ interface vs type | 🟢 ⑤ 함수 타입 선언 | 🟢 ⑥ 유니언 & 인터섹션 타입 | 🟢 ⑦ 타입 추론과 단언 | 🟢 ⑧ 타입 좁히기 | 🟢 ⑨ 제네릭(Generic) | 🟢 ⑩ 유틸리티 타입 | 🟢 ⑪ 고급 타입 조작 | 🔵 ⑫ 조건부 타입
🟢 ① tsconfig.json 완전 정복 | 🟢 ② 개발 환경 세팅 | 🟢 ③ 기본 타입 정복 | 🟢 ④ interface vs type | 🟢 ⑤ 함수 타입 선언 | 🟢 ⑥ 유니언 & 인터섹션 타입 | 🟢 ⑦ 타입 추론과 단언 | 🟢 ⑧ 타입 좁히기 | 🟢 ⑨ 제네릭(Generic) | 🟢 ⑩ 유틸리티 타입 | 🟢 ⑪ 고급 타입 조작 | 🔵 ⑫ 조건부 타입
⚖️ 조건부 타입 (Conditional Types) 완전 정리
조건부 타입은 타입스크립트에서 타입을 조건에 따라 분기할 수 있는 문법입니다.
코드의 if처럼, 타입 안에서 "A면 B, 아니면 C" 같은 논리를 표현할 수 있습니다.
① 기본 문법
T extends U ? X : Y
- 조건: T가 U를 "확장"하는가? - 참일 때: 타입 X - 거짓일 때: 타입 Y
② 간단한 예제
type IsString = T extends string ? 'Yes' : 'No';
type A = IsString; // 'Yes'
type B = IsString; // 'No'
③ 조건부 타입 + 제네릭
함수의 반환 타입, 속성의 타입에 따라 조건을 걸 수 있습니다.
type Flatten = T extends Array<infer U> ? U : T;
type A = Flatten<number[]>; // number
type B = Flatten<string>; // string
infer
를 이용해 배열 내부 타입을 뽑아내는 것도 조건부 타입 활용 예입니다.
④ 분산 조건부 타입
유니언 타입에 조건부 타입을 사용하면 각 타입에 분산 평가가 일어납니다.
type ToArray<T> = T extends any ? T[] : never;
type A = ToArray<string | number>; // string[] | number[]
모든 유니언 멤버에 대해 조건부 타입이 각각 적용됩니다.
type Boxify<T> = T extends any ? T[] : never;
type Box = Boxify<'a' | 1 | true>; // 결과: 'a'[] | 1[] | true[]
// T가 뭐가 오든 그걸 배열로 감싸고 싶을 때. 특히 유니언 타입인 경우, 각 타입마다 배열로 감싸서 반환 (분산 조건부 타입)
//***비교
type OnlyIfArray<T> = T extends any[] ? T : never;
type A = OnlyIfArray<string[]>; // string[]
type B = OnlyIfArray<string>; // never
type C = OnlyIfArray<number[]>; // number[]
// 배열만 통과시키고 나머지는 제거.
⑤ 실전 예: API 응답 타입 분기
type ApiResponse = { // ApiResponse<T> API 응답구조 정의
success: true;
data: T;
} | {
success: false;
error: string;
};
// Apiresponse<T>는 성공했을 때, 실패했을 때 두 가지 중 하나임. 응답의 형태를 정의. 응답의 값은 data에 담음
type ExtractData = T extends { success: true; data: infer D } ? D : never;
// 그 중 성공응답에서 성공 구조를 갖는 경우에만 data값을 추출하는 타입. ExtractData. 응답을 받는 쪽에서 필요.
type Res = ApiResponse<{ name: string }>; //실제 응답 예시
type DataOnly = ExtractData<Res>; // { name: string } // data필드의 타입 추출
// Res는 ApiResponse, ExtractData가 제대로 동작하는지 확인하기 위해 샘플 응답타입을 만듦.
// data 안에 {name:string}이라는 객체가 들어있는 성공/실패 응답 타입을 만들어줘~~~
const response = await api.get<ApiResponse<{ name: string }>>('/user');
// ==================================================================
type GetUserResponse = ApiResponse<{ name: string; age: number }>;
type UserData = ExtractData<GetUserResponse>;
// → { name: string; age: number }
✅ 정리해서 말씀드리면
📤 ApiResponse<T> → 응답을 보내는 쪽 (서버 / 백엔드) 에서 사용
function getUser(): ApiResponse<User> {
return {
success: true,
data: { id: 1, name: '홍길동' },
};
}
- 서버에서 data와 error 구조를 공통으로 맞추기 위해 사용
- 여러 API에서 공통으로 쓰기 위해 제네릭 구조로 만듦
📥 ExtractData<T> → 응답을 받는 쪽 (프론트엔드 / 클라이언트) 에서 사용
type Res = ApiResponse<{ name: string }>;
type DataOnly = ExtractData<Res>;
// DataOnly → { name: string }
const response: Res = await api.get('/user');
if (response.success) {
const user: DataOnly = response.data;
}
- 클라이언트에서는 API 응답에서 data만 추출해서 사용할 일이 많음
- 타입 추론을 통해 data 안의 구조를 쉽게 얻기 위해 ExtractData 같은 헬퍼 타입을 사용
💡 왜 이렇게 분리해서 쓰냐면?
구분역할사용 위치
ApiResponse<T> | 응답의 포맷을 통일 | 서버 (API 반환 타입) |
ExtractData<T> | 성공 시 응답의 data 타입만 추출 | 클라이언트 (응답 처리용) |
✅ 그래서 이런 흐름이 성립합니다:
1. 백엔드에서:
type User = { id: number; name: string };
function getUser(): ApiResponse<User> { ... }
2. 프론트엔드에서:
type Res = ApiResponse<{ id: number; name: string }>;
type User = ExtractData<Res>;
function handleResponse(res: Res) {
if (res.success) {
const user: User = res.data; // 안전하고 추론된 타입!
}
}
📐 요약 정리
형식 | 설명 | 예시 |
---|---|---|
T extends U ? X : Y |
조건 분기 | IsString<T> |
infer |
타입 추론 변수 | infer U |
분산 조건부 | 유니언 각 요소에 분기 적용 | T extends any ? T[] : never |
🧠 마무리
조건부 타입은 복잡한 타입 로직에서 **타입 추론, 선택적 분기, 타입 재구성** 등 정말 다양한 곳에 사용됩니다.
특히 라이브러리, API 응답 처리, Form 데이터 타입 추출 등에서 유용하게 쓰여요.
📘 다음 글 예고
👉 Enum vs Const Enum 차이 – enum은 왜 성능 이슈가 있을까? const enum은 언제 써야 할까?
'language > typescript' 카테고리의 다른 글
🔁 Mapped Type & Template Literal Type – 실전 예제 중심 정리 (1) | 2025.04.27 |
---|---|
🎯 Enum vs Const Enum – 차이점과 실무에서의 선택 기준 (0) | 2025.04.27 |
🧠 고급 타입 조작 – keyof, typeof, infer, extends 완전 정리 (0) | 2025.04.27 |
🔧 유틸리티 타입 – Partial, Pick, Omit 등 실무 핵심 정리 (0) | 2025.04.27 |
📦 제네릭(Generic)의 이해와 사용법 (0) | 2025.04.27 |
댓글