레슨 5 / 8·20분
고급 타입
Mapped Types
Mapped Type은 기존 타입의 각 속성을 변환하여 새로운 타입을 만듭니다. TypeScript의 내장 유틸리티 타입 대부분이 이 방식으로 구현되어 있습니다.
typescript
// Mapped Type 기본 구조
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type Partial<T> = {
[K in keyof T]?: T[K];
};
// 커스텀 Mapped Type
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
interface User {
name: string;
age: number;
email: string;
}
type NullableUser = Nullable<User>;
// { name: string | null; age: number | null; email: string | null }
// as를 사용한 키 리매핑
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
// Getters<User> = { getName: () => string; getAge: () => number; ... }Conditional Types
조건부 타입은 T extends U ? X : Y 형태로, 타입 수준에서 조건 분기를 수행합니다.
typescript
// 조건부 타입
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>; // false
// infer — 타입 추출
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type FnReturn = ReturnType<() => string>; // string
// 배열 요소 타입 추출
type ElementOf<T> = T extends (infer E)[] ? E : never;
type Item = ElementOf<string[]>; // string
// 실전: Promise에서 값 타입 추출
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
type Result = Awaited<Promise<Promise<string>>>; // stringTemplate Literal Types
typescript
// 템플릿 리터럴 타입
type Color = "red" | "blue" | "green";
type Size = "sm" | "md" | "lg";
// 조합 생성
type ClassName = `${Size}-${Color}`;
// "sm-red" | "sm-blue" | "sm-green" | "md-red" | ...
// 이벤트 핸들러 타입
type EventName = "click" | "focus" | "blur";
type Handler = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"
// 내장 문자열 변환 타입
type Upper = Uppercase<"hello">; // "HELLO"
type Lower = Lowercase<"HELLO">; // "hello"
type Cap = Capitalize<"hello">; // "Hello"
type Uncap = Uncapitalize<"Hello">; // "hello"💡
고급 타입은 라이브러리 제작자나 복잡한 타입 시스템을 다룰 때 필요합니다. 일반 애플리케이션 코드에서는 유틸리티 타입(Partial, Pick, Omit, Record)만으로도 대부분 충분합니다.