타입연산자 typeof, keyof, keyof typeof 패턴 정리

2025. 12. 14. 19:17·FrontEnd/TypeScript
  • typeof
    → 이미 존재하는 값의 모양을 그대로 타입으로 쓰고 싶을 때
  • keyof
    → 어떤 타입이 가진 속성 이름 목록이 필요할 때
  • keyof typeof obj
    → 이 객체에 실제로 존재하는 key 이름만 허용하고 싶을 때

아래 예시들만 이해되면 실무에서 바로 써먹을 수 있다.


1. typeof – 값에서 타입 뽑아 쓰기

CONFIG 같은 설정 객체를 하나 만들어 놨는데,
이 구조와 완전히 똑같은 타입이 필요하다

const CONFIG = {
  retryCount: 3,
  timeoutMs: 5000,
  baseUrl: "https://api.example.com",
}

// CONFIG와 같은 모양의 타입 만들기
type Config = typeof CONFIG

 

Config는 아래와 같은 타입으로 인식된다

type Config = {
  retryCount: number
  timeoutMs: number
  baseUrl: string
}

왜 이렇게 쓰냐?

이유 두 가지.

  1. 타입을 두 번 안 적어도 된다.
    • 객체 한 번, 타입 한 번 이렇게 중복 정의할 필요 없음
  2. 구조가 바뀌면 타입도 자동으로 같이 바뀐다.
    • CONFIG에 필드를 추가하거나 이름을 바꾸면
      Config 타입도 거기에 맞춰서 자동으로 변경

느낌만 잡으면 된다.

typeof = "이 값처럼 생긴 타입 하나 만들어 줘"


2. keyof – 타입에서 키 이름만 뽑기

이번엔 반대 방향이다.
타입 → 키 이름.

type User = {
  id: number
  name: string
  email: string
}

// User가 가진 key 이름들을 뽑아서 유니온 타입으로 만들기
type UserKey = keyof User
// "id" | "name" | "email"

어디에 쓰면 좋냐?

예를 들어, User의 key만 받을 수 있는 함수를 만들고 싶을 때.

type User = {
  id: number
  name: string
  email: string
}

type UserKey = keyof User

function getUserField(user: User, key: UserKey) {
  return user[key]
}

getUserField({ id: 1, name: "Lee", email: "x" }, "name")  // OK
getUserField({ id: 1, name: "Lee", email: "x" }, "age")   // 에러

이렇게 해두면:

  • 존재하지 않는 키(예: "age")를 쓰면 바로 컴파일 에러
  • "User가 가진 키만 써라" 라는 조건을 타입으로 강제할 수 있다.

keyof = "이 타입이 가진 속성 이름들을 문자열 유니온으로 줘"


3. keyof typeof – 상수 객체의 key만 허용하기

실무에서 제일 자주 보는 패턴

상수 객체로 라우트, API 경로, 색상 토큰 등을 관리하고 있는데,
이 객체에 정의된 key만 쓸 수 있게 타입으로 막고 싶다.

3-1. 색상 토큰 예시

const COLORS = {
  primary: "#3465ff",
  danger: "#ff4d4f",
  success: "#52c41a",
} as const

// COLORS가 가진 key 이름들만 허용하는 타입
type ColorName = keyof typeof COLORS
// "primary" | "danger" | "success"

function setThemeColor(name: ColorName) {
  document.body.style.setProperty("--theme-color", COLORS[name])
}

setThemeColor("primary")  // OK
setThemeColor("wrong")    // 에러

여기서 일어나는 일은 딱 두 단계다.

  1. typeof COLORS
    → COLORS라는 값의 타입을 가져온다.
  2. keyof typeof COLORS
    → 그 타입이 가진 key 이름만 유니온으로 뽑는다.
    결과: "primary" | "danger" | "success"

이 패턴을 쓰면

  • 문자열을 직접 "primary", "danger"처럼 막 쓰지 않아도 되고
  • COLORS 객체 기준으로만 유효한 값이 정해진다.

3-2. 라우트/메뉴 키에도 그대로 응용 가능

const ROUTES = {
  home: "/",
  settings: "/settings",
  profile: "/profile",
} as const

// ROUTES의 key 이름만 허용
type RouteName = keyof typeof ROUTES

function navigate(name: RouteName) {
  window.location.href = ROUTES[name]
}

navigate("home")     // OK
navigate("dashboard") // 에러

이렇게 하면:

  • 라우트 이름을 바꾸거나 추가했을 때
  • 타입 에러로 잘못된 부분들을 먼저 발견할 수 있다.

keyof typeof obj = "이 객체에 실제로 존재하는 key만 쓸 수 있게 막자"


4. 언제 어떤 걸 떠올리면 되는지

4-1. typeof를 떠올릴 타이밍

  • 이미 값(객체, 함수 등)이 있는데, 그 구조를 그대로 타입으로 쓰고 싶다.
  • 타입 정의를 값과 따로 두 번 쓰고 싶지 않다.
const CONFIG = { ... } as const
type Config = typeof CONFIG

4-2. keyof를 떠올릴 타이밍

  • "이 타입이 가진 키 이름들만 허용하고 싶다"는 요구가 있을 때.
  • 특정 타입의 key만 인자로 받는 함수를 만들고 싶을 때.
type UserKey = keyof User
function getUserField(user: User, key: UserKey) { ... }

4-3. keyof typeof를 떠올릴 타이밍

  • 상수 객체(ROUTES, COLORS, API_PATHS 등)를 이미 쓰고 있다.
  • 이 객체에 정의된 key 이외의 문자열은 막고 싶다.
const API_PATHS = {
  list: "/api/users",
  detail: "/api/users/:id",
  me: "/api/me",
} as const

type ApiPathName = keyof typeof API_PATHS

function fetchApi(name: ApiPathName) {
  const url = API_PATHS[name]
  // ...
}

5. 완전 핵심 요약

  • typeof
    → "이 값처럼 생긴 타입 하나 만들어 줘"
  • keyof
    → "이 타입이 가진 속성 이름들만 문자열 유니온으로 줘"
  • keyof typeof obj
    → "이 상수 객체에 실제로 있는 key만 쓸 수 있게 막자"

CONFIG, ROUTES, COLORS처럼 상수 객체 + 타입을 같이 다루는 연습을 하다 보면,
실무 코드에서 자연스럽게 typeof, keyof, keyof typeof를 떠올리게 된다

저작자표시 비영리 변경금지 (새창열림)

'FrontEnd > TypeScript' 카테고리의 다른 글

TypeScript as const 이게 뭘까  (0) 2025.12.18
TypeScript 유틸리티 타입 Partial<T> – 부분만 채워도 되는 타입 만들기  (1) 2025.12.14
TypeScript 유틸리티 타입 Omit<T, K> – 필요 없는 필드만 쏙 빼고 쓰기  (0) 2025.12.14
TypeScript 유틸리티 타입 Pick<T, K> – 객체 타입에서 필요한 것만 뽑아 쓰기  (0) 2025.12.13
setTimeout() 반환값 정리 – 브라우저 vs Node에서 뭐가 다른지  (0) 2024.11.24
'FrontEnd/TypeScript' 카테고리의 다른 글
  • TypeScript 유틸리티 타입 Partial<T> – 부분만 채워도 되는 타입 만들기
  • TypeScript 유틸리티 타입 Omit<T, K> – 필요 없는 필드만 쏙 빼고 쓰기
  • TypeScript 유틸리티 타입 Pick<T, K> – 객체 타입에서 필요한 것만 뽑아 쓰기
  • setTimeout() 반환값 정리 – 브라우저 vs Node에서 뭐가 다른지
프론트엔드 개발자 jbeat
프론트엔드 개발자 jbeat
프론트엔드 개발자 블로그인데 일상도 쪼그으믐
  • 프론트엔드 개발자 jbeat
    jbeat 님의 블로그
    프론트엔드 개발자 jbeat
  • 전체
    오늘
    어제
    • 분류 전체보기 (44)
      • FrontEnd (43)
        • TypeScript (6)
        • JavaScript (18)
        • Next.js (3)
        • React (1)
        • Testing (2)
        • Third Party (1)
        • web (10)
        • Tooling (1)
        • coding test (0)
        • A.I (1)
      • 일상 (1)
        • wedding (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 태그

    Utility
    Android
    코테
    타입스크립트
    고차함수
    omit
    pick
    컬렉션
    이터러블
    WebSocket
    CrossOrigin
    preconnect
    TypeScript
    playwright
    javascript
    yjs
    주니어
    배열
    CRDT
    Next.js
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
프론트엔드 개발자 jbeat
타입연산자 typeof, keyof, keyof typeof 패턴 정리
상단으로

티스토리툴바