본문 바로가기
C.W.K.
Stream
Lesson 01 of 06 · published

`keyof`: 키의 집합을 타입으로 꺼내기

~8 min · type-manipulation, keyof, key-extraction

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"keyof는 객체의 열쇠 꾸러미를 값이 아니라 타입으로 건네줘."

객체 모양에서 이름만 꺼내기

keyof TT가 가질 수 있는 프로퍼티 이름을 문자열 리터럴의 합집합으로 만든다. type User = { id: number, name: string }라면 keyof User'id' | 'name'이야. 객체를 한 번 정의한 뒤 같은 키 목록을 다른 곳에 손으로 옮겨 적지 않아도 되는 셈이지.

가장 흔한 쓰임은 안전한 프로퍼티 접근이야. function get<T, K extends keyof T>(obj: T, key: K): T[K]처럼 쓰면 호출자는 실제로 존재하는 키만 넘길 수 있어. 반환 타입도 선택한 키에 맞춰 따라오니 get(user, 'name')string으로 추론되고, 오타인 'nmae'는 실행 전에 막혀.

배열에서는 무엇이 키일까

keyof string[]에는 숫자 인덱스만 들어 있지 않아. lengthpush 같은 배열 멤버도 모두 키이므로 결과가 생각보다 넓어져. 배열의 원소 타입을 얻고 싶은데 keyof를 쓰면 엉뚱한 문을 연 셈이야. 그때는 string[][number]처럼 숫자 인덱스 접근을 써야 해.

튜플도 같은 원리지만 각 위치 정보가 더 구체적이야. readonly [string, number]의 키에는 두 자리와 공통 배열 멤버가 함께 들어간다. 그래서 라이브러리 타입을 읽을 때는 '키의 집합이 필요한가, 원소 타입이 필요한가'를 먼저 구분해야 해.

키와 값의 관계 잇기

T[keyof T]는 모든 프로퍼티 값 타입의 합집합이야. type Config = { port: number, secure: boolean }라면 결과는 number | boolean이지. keyof가 이름의 범위를 만들고, 인덱스 접근이 그 이름에 대응하는 값을 꺼내는 역할을 나눠 맡아.

반대 방향으로는 Object.keys()가 있어. 이것은 런타임 문자열 배열을 반환하므로 타입 수준의 keyof와 똑같지 않아. 정적 타입이 실제 데이터 검증을 대신한다고 착각하면 안 돼. 외부 JSON은 여전히 런타임에서 확인해야 하지.

keyof는 객체를 복제하지 않고 그 객체가 허용하는 이름의 경계를 재사용하는 도구야. 키 목록을 따로 관리하기 시작했다면 먼저 keyof로 한 선언에서 파생할 수 있는지 봐.

Code

keyof 기본과 쌍·typescript
interface User { id: number; name: string; email: string }

type UserKeys = keyof User;            // 'id' | 'name' | 'email'

// keyof 통한 타입-안전 property 접근.
function prop<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const u = { id: 1, name: 'Pippa', email: 'a@b.c' };
prop(u, 'name');     // string
prop(u, 'id');       // number
// prop(u, 'xyz');    // ❌ 'xyz' 가 u 의 key 아님

// 모든 값: T[keyof T]
type UserValues = User[keyof User];    // number | string

// 배열: keyof 가 index AND method 포함.
type A = keyof string[];               // 'length' | 'push' | ... | number
type Element = string[][number];       // string (element 타입 — 보통 답)

External links

Exercise

host, port, debug 키를 가진 Config에서 getOption<K extends keyof Config>(key: K): Config[K]를 작성해. 각 키를 호출해 반환 타입이 필드 타입과 맞는지 확인하고, 존재하지 않는 키를 넘겼을 때의 오류도 읽어 봐.
Hint
host를 넘기면 문자열, port를 넘기면 숫자가 반환되어야 해. K extends keyof Config가 키 오타를 호출 자리에서 막아.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.