반응형
맵드 타입
맵드 타입은 기존의 객체 타입을 기반으로 새로운 객체 타입을 만드는 마법같은 타입 조작 기능입니다.
예제와 함께 살펴보겠습니다. 이번에는 유저 정보를 관리하는 간단한 프로그램의 일부분을 만든다고 가정합니다. 먼저 유저 객체 타입을 정의합니다.
interface User {
id: number;
name: string;
age: number;
}
다음으로는 유저 정보가 서버에 저장되어 있다고 가정하고, 한명의 유저 정보를 불러오는 기능을 함수로 만듭니다.
interface User {
id: number;
name: string;
age: number;
}
function fetchUser(): User {
return {
id: 1,
name: "이정환",
age: 27,
};
}
그리고 한 명의 유저 정보를 수정하는 기능도 만들어 주겠습니다. 실제로 서버가 존재하는 것은 아니니까 함수 내부는 구현 했다고 치고 주석으로 비워두겠습니다.
interface User {
id: number;
name: string;
age: number;
}
function fetchUser(): User {
(...)
}
function updateUser(user: User) {
// ... 유저 정보 수정 기능
}
updateUser 함수는 수정된 유저 객체를 받아 유저 정보를 수정합니다.
따라서 유저 정보를 수정 하려면 다음과 같이 이 함수를 호출하고 여러개의 정보 중 수정하고 싶은 프로퍼티만 전달 해 주면 됩니다.
interface User {
id: number;
name: string;
age: number;
}
function fetchUser(): User {
(...)
}
function updateUser(user: User) {
// ... 유저 정보 수정 기능
}
updateUser({ // ❌
age: 25
});
그런데 updateUser 함수의 매개변수 타입이 User 타입으로 되어 있어서 수정하고 싶은 프로퍼티만 골라서 보낼 수 없는 상황입니다.
따라서 어쩔 수 없이 다음과 같이 새로운 타입을 만들어 주어야 합니다.
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = {
id?: number;
name?: string;
age?: number;
}
(...)
function updateUser(user: PartialUser) {
// ... 유저 정보 수정 기능
}
updateUser({ // ✅
age: 25
});
그럼 이제 수정하길 원하는 프로퍼티만 전달할 수 있도록 기능을 수정했습니다.
그런데 User 타입과 PartialUser 타입이 지금 서로 중복된 프로퍼티를 정의하고 있습니다. 중복은 언제나 좋지 않습니다. 따라서 이럴 때 바로 맵드 타입을 이용하면 좋습니다.
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = {
[key in "id" | "name" | "age"]?: User[key];
};
(...)
PartialUser 타입을 맵드 타입을 이용해 아까와 동일한 타입으로 정의했습니다.
문법을 자세히 살펴보면 다음과 같습니다
[key in “id” | “name” | “age”] 는 이 객체 타입은 key가 한번은 id, 한번은 name, 한번은 age가 된다는 뜻 입니다. 따라서 다음과 같이 3개의 프로퍼티를 갖는 객체 타입으로 정의됩니다.
- key가 “id” 일 때 → id : User[id] → id : number
- key가 “name”일 때 → name : User[user] → name : string
- key가 “age”일 때 → age : User[age] → age : number
여기에 대 괄호 뒤에 선택적 프로퍼티를 의미하는 물음표(?) 키워드가 붙어있으므로 모든 프로퍼티가 선택적 프로퍼티가 되어 결론적으로 이 타입은 다음과 같은 타입이 됩니다.
{
id?: number;
name?: string;
age?: number;
}
이렇듯 맵드 타입을 이용하면 간단한 한줄의 코드 만으로 중복 없이 기존 타입을 변환할 수 있습니다.
여기서 이전 시간에 배운 keyof 연산자를 이용해 한번 더 업그레이드 하면 다음과 같습니다.
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = {
[key in keyof User]?: User[key];
};
(...)
마지막으로 맵드 타입을 이용해 모든 프로퍼티가 읽기 전용 프로퍼티가 된 타입을 만들면 다음과 같습니다.
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = {
[key in keyof User]?: User[key];
};
type ReadonlyUser = {
readonly [key in keyof User]: User[key];
};
(...)
반응형
'TypeScript' 카테고리의 다른 글
TypeScript : 분산적인 조건부 타입 (0) | 2024.08.12 |
---|---|
TypeScript : 조건부 타입 (0) | 2024.08.12 |
TypeScript : keyof & typeof 연산자 (0) | 2024.08.10 |
TypeScript : 인덱스드 엑세스 타입 (0) | 2024.08.10 |
TypeScript : 프로미스와 제네릭 (0) | 2024.08.09 |