map()
API 함수를 타입에 적용한 것과 같은 효과맵드 타입은 자바스크립트의 map
함수를 타입에 적용했다고 보면된다.
이를 위해서는 아래와 같은 형태의 문법을 사용해야 한다.
{ [ P in K ] : T }
{ [ P in K ] ? : T }
{ readonly [ P in K ] : T }
{ readonly [ P in K ] ? : T }
헐크, 토르, 캡틴을 유니온 타입으로 묶어주는 Heroes
라는 타입이 있다.
type Heroes = 'Hulk' | 'Thor' | 'Capt';
여기서 이 세 영웅의 이름에 각각 나이까지 붙인 객체를 만들고 싶을때 아래와 같이 작성할 수 있다.
type HeroProfiles = { [K in Heroes]: number };
// { Hulk: number } 첫번째 순회
// { Thor: number } 두번째 순회
// { Capt: number } 세번째 순회
// 결과
// type HeroProfiles = {
// Hulk: number;
// Thor: number;
// Capt: number;
// }
const heroInfo: HeroProfiles = {
Hulk: 54,
Thor: 1000,
Capt: 33,
}
위 코드에서 [K in Heroes]
부분은 마치 자바스크립트의 for in
문법과 유사하게 동작한다.
앞에서 정의한 Heroes
타입의 3개의 문자열을 각각 순회하여 number
타입을 값으로 가지는 객체의 키로 정의가 된다.
실제로 서비스를 개발할 때는 아래와 같은 코드를 많이 사용하게 된다.
// 키와 값이 있는 객체를 정의하는 타입을 받아 그 객체의 부분 집합을 만족하는 타입으로 변환
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> = {};
아래와 같이 사용자 프로필을 조회하는 API 함수가 있다고 했을 때
이 프로필의 정보를 수정하는 API는 아마 아래와 같은 형태일 것입니다.
interface UserProfile {
username: string;
email: string;
profilePhotoUrl: string;
}
interface UserProfileUpdate {
username?: string;
email?: string;
profilePhotoUrl?: string;
}
function fetchUserProfile(): UserProfile {
// ...
}
function updateUserProfile(params: UserProfileUpdate) {
// ...
}
위의 인터페이스에서 반복되는 구조를 아래와 같은 방식으로 재활용 할 수 있다.