노트

매핑된 타입과 keyof

Mapped Types

프런트엔드#ts · 연결된 개념 8개

쉽게 말하면

매핑된 타입은 엑셀 표의 모든 행에 같은 수식을 한 번에 채우듯, 기존 타입의 키를 하나씩 돌며 새 타입을 찍어 내는 문법이에요. 같은 모양을 손으로 두 번 쓰지 않아도 돼요.

비유가 깨지는 곳 수식과 달리 값이 아니라 타입을 바꿔요. readonly나 ?를 -로 떼어 수정 가능한 사본을 만들 수 있고, Partial·Readonly·Pick 같은 내장 유틸리티 타입도 이 문법으로 만들어져 있어요.

매핑된 타입(Mapped Types)은 기존 타입의 키를 하나씩 돌며 새 타입을 만드는 문법([K in keyof T]: …)이다. keyof T는 객체 타입의 키 유니언을, T[K](인덱스 접근 타입, Indexed Access Type)는 그 키의 값 타입을 꺼낸다.

type User = { id: string; age: number }
type UserKeys = keyof User                  // 'id' | 'age'
type Age = User['age']                      // number
type Nullable<T> = { [K in keyof T]: T[K] | null }
type ValueOf<T> = T[keyof T]

수정자(Mapping Modifiers) 더하고 빼기

readonly와 ?를 붙이거나 -로 뗄 수 있다. 읽기 전용 타입을 폼 상태처럼 고칠 수 있는 사본으로 바꿀 때 쓴다.

type Mutable<T> = { -readonly [K in keyof T]: T[K] }
type Concrete<T> = { [K in keyof T]-?: T[K] }

(obj as any).field = …로 우회하는 것보다 의도가 드러나고 나머지 검사는 유지된다.

상수 객체에서 유니언 뽑기

const routes = { home: '/', profile: '/profile' } as const
type RouteName = keyof typeof routes          // 'home' | 'profile'
type RoutePath = (typeof routes)[RouteName]   // '/' | '/profile'

라우트·권한·이벤트 이름을 값과 타입 두 군데에 따로 선언하지 않아도 된다. enum 대신 이 패턴을 쓰는 이유는 enum과 as const 객체에 있다.

  • <K extends keyof T> 제약과 함께 쓰면 테이블 컬럼 정의나 폼 필드 접근을 안전하게 만들 수 있다(제네릭)
  • 키 이름 자체를 바꾸려면 템플릿 리터럴 타입와 as 절을 쓴다
  • 내장 유틸리티 타입(Partial, Readonly, Pick)가 모두 이 문법으로 구현돼 있다

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 유니언·인터섹션·리터럴 타입

    유니언 타입(Union Type, A | B)은 "A이거나 B인 값"이고, 인터섹션 타입(Intersection Type, A & B)은 "A이면서 B인 값"이다. 리터럴 타입(Literal Type)은 'left'나 3처럼 특정 값 하나만 허용하는 타입이다.

  • 기본형 집착

    전화번호·금액·우선순위 같은 도메인 개념을 끝까지 문자열이나 숫자로만 다루는 냄새. 같은 검증과 포맷 코드가 여기저기 반복되고, 문자열로 모든 걸 표현하는 "stringly typed" 코드가 된다.

  • any와 unknown

    any는 그 값에 대한 타입 검사를 포기하는 타입이고, unknown은 타입을 아직 모르니 확인하기 전에는 쓰지 못하게 하는 타입이다. 둘 다 아무 값이나 받을 수 있지만, 꺼내 쓸 때가 다르다.

  • 함수 오버로드와 시그니처

    함수 오버로드(Function Overloads)는 구현 하나 위에 호출 방식별 시그니처를 여러 개 선언해, 인자 조합에 따라 정확한 반환 타입이 추론되게 하는 TypeScript 기능이다.

  • 타입 추론과 타입 검사

    타입 추론(Type Inference)은 표기가 없어도 컴파일러가 값의 타입을 정하는 단계이고, 타입 검사(Type Checking)는 정해진(추론됐거나 명시된) 타입을 코드가 지키는지 확인하는 단계다. 보통 추론이 먼저 일어나고, 그 결과를 기준으로 검사한다.

보기 옵션