맵드 타입은 기존의 객체 타입을 기반으로 새로운 객체 타입을 만드는 기능이다.
// 유저 객체 타입
interface User {
id: number;
name: string;
age: number;
}
// 한 명의 유저 정보를 불러오는 기능
function fetchUser(): User {
// ... 기능
return {
id: 1,
name: "woodstock",
emotion: "good",
};
}
// 한 명의 유저 정보를 수정하는 기능
function updateUser(user: User) {
// ... 수정하는 기능
}
우리는 updateUser
함수를 호출하여 유저 정보를 수정 하려고 하는데, updateUser
함수의 매개변수 타입이 User
타입으로 되어있어 수정하고 싶은 프로퍼티만 골라서 보낼 수 없는 상황이다.
이 상황을 해결하기 위해 새로운 타입을 만들어보자.
type PartialUser = {
id?: number;
name?: string;
skill?: string;
};
// 중략...
function updateUser(user: PartialUser) {
// ... 수정하는 기능
}
에러는 사라졌지만, 결과적으로 User
타입과 PartialUser
타입이 서로 중복된 프로퍼티를 정의하고 있어 좋지 않다.
이럴 때 맵드 타입을 이용해 개선할 수 있다.
interface User {
id: number;
name: string;
skill: string;
}
type PartialUser = {
[key in "id" | "name" | "skill"]?: User[key];
};
// 한 명의 유저 정보를 불러오는 기능
function fetchUser(): User {
// ... 기능
return {
id: 1,
name: "woodstock",
skill: "JavaScript",
};
}
// 한 명의 유저 정보를 수정하는 기능
function updateUser(user: PartialUser) {
// ... 수정하는 기능
}
updateUser({
skill: "TypeScript",
});
맵드타입과 keyof 연산자는 함께 이용할 수 있다.
// 적용 전
type BooleanUser = {
[key in "id" | "name" | "skill"]: boolean;
};
// 적용 후
type BooleanUser = {
[key in keyof User]: boolean;
};
또, 맵드 타입을 이용해 모든 프로퍼티가 읽기 전용 프로퍼티가 된 타입을 만들수도 있다.
type ReadonlyUser = {
readonly [key in keyof User]: User[key];
};
한 가지 주의할 점은, 맵드타입은 인터페이스에서는 사용할 수 없고 무조건 타입 별칭으로만 사용이 가능하다.