타입스크립트에서 자주 쓰이는 타입 레벨 트릭들

dongEon·2025년 8월 27일
0
post-thumbnail

타입스크립트를 공부하다 보면 단순한 문법을 넘어서 트릭처럼 느껴지는 문법 패턴들을 만나게 됩니다.
이 글에서는 그중에서도 유니온 추출 / 매핑 후 값 유니온화 / 튜플 원소 타입 뽑기 같은 핵심 패턴을 정리합니다.


1. T[number] → 배열/튜플 원소 타입 유니온

개념

  • 배열 타입 T[number]를 붙이면, 해당 배열의 모든 원소 타입을 유니온으로 추출합니다.

예시

type Roles = ["guest", "user", "admin"];
type Union = Roles[number];
// "guest" | "user" | "admin"

👉 튜플이든 배열이든, [number]는 “이 타입에서 나올 수 있는 모든 값들의 합집합”을 의미합니다.
즉, 런타임 반복이 아니라 타입 레벨 유니온 추출이에요.


2. Obj[keyof Obj] → 객체 value 타입 유니온

개념

  • 객체 타입에서 keyof Obj는 키들의 유니온.
  • 다시 Obj[keyof Obj]를 하면, 그 키들에 해당하는 모든 value 타입을 유니온으로 가져옵니다.

예시

type Obj = {
  a: number;
  b: string;
};

type Values = Obj[keyof Obj];
// number | string

👉 이 패턴은 “객체의 모든 value 타입을 유니온으로 만들고 싶을 때” 사용합니다.


3. { [P in keyof T]: ... }[keyof T] → 매핑 후 값 유니온 뽑기

개념

  • 매핑 타입으로 키를 순회하면서 조건을 걸어 값을 생성.
  • 마지막에 [keyof T]로 인덱싱하면, 생성된 객체의 value들을 유니온으로 모아 추출합니다.

예시

type Obj = { a: 1; b: 2; c: 3 };

type PickEven<T> = {
  [P in keyof T]: T[P] extends 2 ? P : never
}[keyof T];

type Result = PickEven<Obj>;
// "b"

👉 ...}[keyof T] 트릭은 매핑 타입 결과를 다시 유니온으로 만드는 핵심 패턴입니다.


4. 트릭 조합 실전: Problem 03 – auth-guards

이제 위의 트릭을 합쳐서, 특정 역할(Role)에 따라 접근 가능한 경로를 타입으로 구하는 문제를 풀어보겠습니다.

요구사항

  • Role: "guest" | "user" | "admin"
  • RouteMap: 각 path에 접근 가능한 role 리스트를 정의
  • AccessibleRoutes: 역할 R이 접근 가능한 path들의 유니온

풀이

export type Role = "guest" | "user" | "admin";

export type RouteMap = {
  "/": { roles: ["guest", "user", "admin"] };
  "/login": { roles: ["guest"] };
  "/dashboard": { roles: ["user", "admin"] };
  "/settings": { roles: ["admin"] };
};

export type AccessibleRoutes<R extends Role> = never // 초기 상태

// AccessibleRoutes<R> 기대값
// ----------------------------
type G = AccessibleRoutes<"guest">;
type G_Expected = "/" | "/login";
type _g = Expect<Equal<G, G_Expected>>;

type U = AccessibleRoutes<"user">;
type U_Expected = "/" | "/dashboard";
type _u = Expect<Equal<U, U_Expected>>;

type A = AccessibleRoutes<"admin">;
type A_Expected = "/" | "/dashboard" | "/settings" | "/login";
type _a = Expect<Equal<A, A_Expected>>;


정답
// 1. 특정 path의 roles 유니온 추출
type RouteRoles<P extends keyof RouteMap> = RouteMap[P]["roles"][number];

// 2. 매핑 타입 + 조건부 타입 → 접근 가능한 path 필터링
export type AccessibleRoutes<R extends Role> = {
  [P in keyof RouteMap]: R extends RouteRoles<P> ? P : never
}[keyof RouteMap];

결과

  • AccessibleRoutes<"guest">"/" | "/login"
  • AccessibleRoutes<"user">"/" | "/dashboard"
  • AccessibleRoutes<"admin">"/" | "/dashboard" | "/settings"

✅ 결론

  • T[number]: 배열/튜플 원소 타입을 유니온으로 추출하는 패턴
  • Obj[keyof Obj]: 객체의 value 타입들을 유니온으로 추출하는 패턴
  • { [P in keyof T]: ... }[keyof T]: 매핑 타입 후 값을 다시 유니온으로 모으는 패턴
profile
개발 중에 마주한 문제와 해결 과정, 새롭게 배운 지식, 그리고 알고리즘 문제 해결에 대한 다양한 인사이트를 공유하는 기술 블로그입니다

0개의 댓글