해당 게시글은
강의 사이트, 인프런에서 이정환님이 진행하시는
'한 입 크기로 잘라먹는 타입스크립트' 를
들어보며 블로그를 작성하려고 합니다.
다음 게시글 내용은 해당 강의에 핸드북의 내용으로
출처는 다음과 같습니다.
https://ts.winterlood.com/7250edd7-a3fd-4662-b756-f11f927c73f2
타입스크립트를 소개합니다 - 타입스크립트 개론
한 입 크기로 잘라먹는 타입스크립트
ts.winterlood.com
section8/chapter3.ts 에서 실습을 진행했습니다.
맵드 타입
맵드 타입은 기존의 객체 타입을 기반으로 새로운 객체 타입을 만드는
마법같은 타입 조작 기능입니다.
예제와 함께 살펴보겠습니다.
이번에는 유저 정보를 관리하는 간단한 프로그램의 일부분을 만든다고 가정합니다.
먼저 유저 객체 타입을 정의합니다.
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" 일 때 → id : User[user] → name : string
- key 가 "age" 일 때 → id : 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 > 한 입 크기로 잘라먹는 타입스크립트' 카테고리의 다른 글
[조건부 타입] 조건부 타입 (0) | 2023.07.21 |
---|---|
[타입 조작하기] 템플릿 리터럴 타입 (0) | 2023.07.20 |
[타입 조작하기] keyof & typeof 연산자 (0) | 2023.07.20 |
[타입 조작하기] 인덱스드 엑세스 타입 (0) | 2023.07.20 |
[타입 조작하기] 타입 조작이란 (0) | 2023.07.20 |