기존의 객체 타입을 기반으로 새로운 객체 타입을 만드는 타입 조작 기능
유저 정보를 관리하는 간단한 프로그램의 일부분을 만든다고 가정.
먼저 유저 객체 타입을 정의함
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 타입과 PartialUsre 타입이 지금 서로 중복된 프로퍼티를 정의하고 있음. 중복은 언제나 좋지 않음. 따라서 이럴 때 맵드 타입을 이용하면 됨
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = {
[key in "id" | "name" | "age"]?: User[key];
};
(...)문법을 보면.
[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];
};
(...)