인덱스 접근 타입 — T[K]로 타입 추출

TypeScript 인덱스 접근 타입(Indexed Access Types) T[K] 문법, 중첩 접근, 배열 요소 타입 추출, API 응답 타입 DRY 패턴을 완전히 정리합니다.

· 3 min read · PALDYN Team

지난 글에서 keyof와 typeof를 살펴봤다. 이번에는 인덱스 접근 타입(Indexed Access Types)을 다룬다. 기존 타입에서 특정 프로퍼티의 타입을 추출하는 T[K] 문법이다.

기본 문법

interface User {
  id:        number;
  name:      string;
  address: {
    city:    string;
    country: string;
  };
}

type UserId      = User["id"];       // number
type UserName    = User["name"];     // string
type UserAddress = User["address"];  // { city: string; country: string }
type UserCity    = User["address"]["city"]; // string — 중첩 접근

T["key"] 형태로 타입에서 특정 키의 타입을 추출한다. 타입 레벨의 프로퍼티 접근이다.

인덱스 접근 타입 기본

keyof와 조합

type UserValues = User[keyof User];
// number | string | { city: string; country: string }
// — User의 모든 값 타입 유니언

T[keyof T]는 타입의 모든 값 타입의 유니언을 만든다.

배열 요소 타입

배열 타입에 number를 인덱스로 사용하면 배열 요소의 타입을 추출할 수 있다.

const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
];

type UserArrayElement = typeof users[number];
// { id: number; name: string }

as const 배열과 결합하면 리터럴 유니언을 만들 때도 사용한다.

const COLORS = ["red", "green", "blue"] as const;
type Color = typeof COLORS[number]; // "red" | "green" | "blue"

API 응답 타입 DRY 패턴

인덱스 접근 타입 고급 패턴

중복 없이 타입을 파생시키는 핵심 패턴이다.

interface ApiResponse {
  user:    { id: string; name: string; role: "admin" | "user" };
  posts:   { id: string; title: string; content: string }[];
  meta:    { total: number; page: number; pageSize: number };
}

// 중복 선언 없이 파생 타입 생성
type UserData  = ApiResponse["user"];
type PostItem  = ApiResponse["posts"][number];
type PaginationMeta = ApiResponse["meta"];
type UserRole  = ApiResponse["user"]["role"]; // "admin" | "user"

ApiResponse의 구조가 바뀌면 파생 타입도 자동으로 업데이트된다.

제네릭과 조합

// 특정 키의 타입으로 타입을 제약
function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
  return items.map(item => item[key]);
}

const names = pluck(users, "name"); // string[] ✅
const ids   = pluck(users, "id");   // number[] ✅
const ages  = pluck(users, "age");  // TS2345 ❌

T[K][]는 “T의 K 키 타입의 배열”이다. pluck의 반환 타입이 키에 따라 정확하게 추론된다.

조건부 타입과 조합

type NonNullableProperty<T, K extends keyof T> =
  NonNullable<T[K]>;

interface Config {
  host:    string | null;
  port:    number;
  timeout: number | undefined;
}

type Host    = NonNullableProperty<Config, "host">;    // string
type Port    = NonNullableProperty<Config, "port">;    // number
type Timeout = NonNullableProperty<Config, "timeout">; // number

인덱스 접근 타입은 고급 타입 조합의 필수 재료다.


지난 글: keyof와 typeof — 타입에서 키를 추출하다

다음 글: 구조적 타이핑 — TypeScript가 타입을 비교하는 방법


읽어주셔서 감사합니다. 😊