Learning
레슨 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>>>; // string

Template 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)만으로도 대부분 충분합니다.