본문 바로가기
프로그래밍/typescsript

타입스크립트의 Mapped Type(맵드 타입)

by 한코코 2022. 11. 23.

타입스크립트에서 map처럼 타입을 각각 변환하는 방법이며 아래와 같은 형태의 문법을 사용해야 한다.

{ [ P in K ] : T }
{ [ P in K ] ? : T }
{ readonly [ P in K ] : T }
{ readonly [ P in K ] ? : T }

 

 

기본 예제

히어로들의 이름에 각각 나이까지 붙인 객체를 만들고 싶다면 아래와 같이 코드를 사용하면 된다.

type Heroes = 'Hulk' | 'Thor' | 'Capt';

// for in 문법과 유사한 K in Heroes
type HeroProfiles = { [K in Heroes]: number };
const heroInfo: HeroProfiles = {
  Hulk: 54,
  Thor: 1000,
  Capt: 33,
}

위 코드에서 [K in Heroes] 부분은 마치 자바스크립트의 for in 문법과 유사하게 동작한다.

앞에서 정의한 Heroes 타입의 3개의 문자열을 각각 순회하여 number 타입을 값으로 가지는 객체의 키로 정의가 된다.

{ Hulk: number } // 첫번째 순회
{ Thor: number } // 두번째 순회
{ Capt: number } // 세번째 순회

따라서 위의 원리가 적용된 HeroProfiles의 타입은 다음과 같다.

type HeroProfiles = {
  Hulk: number;
  Thor: number;
  Capt: number;
}

 

 

 

실용 예제 1

다음은 실질적으로 자주 사용하게되는 코드다.

이 문법은 키와 값이 있는 객체를 정의하는 타입을 받아 그 객체의 부분 집합을 만족하는 타입으로 변환해준다.

type Subset<T> = {
  [K in keyof T]?: T[K];
}

위 문법을 사용하면 다음과 같은 객체를 모두 정의할 수 있다.

interface Person {
  age: number;
  name: string;
}

const ageOnly: Subset<Person> = { age: 23 };
const nameOnly: Subset<Person> = { name: 'Tony' };
const ironman: Subset<Person> = { age: 23, name: 'Tony' };
const empty: Subset<Person> = {};

 

 

 

실용 예제 2

interface UserProfile {
  username: string;
  email: string;
  profilePhotoUrl: string;
}

interface UserProfileUpdate {
  username?: string;
  email?: string;
  profilePhotoUrl?: string;
}

동일한 타입에 대해서 반복해서 선언하는 것을 피하기 위해 아래 코드처럼 정리할 수 있다.

type UserProfileUpdate = {
  username?: UserProfile['username'];
  email?: UserProfile['email'];
  profilePhotoUrl?: UserProfile['profilePhotoUrl'];
}

// 좀더 줄여보기
type UserProfileUpdate = {
  [p in 'username' | 'email' | 'profilePhotoUrl']?: UserProfile[p]
}

// keyof를 사용해 좀더 줄여보기
type UserProfileUpdate = {
  [p in keyof UserProfile]?: UserProfile[p]
}

 

 

참고 사이트 : 공식 타입스크립트 핸드북

댓글