[Typescript] Utility Types

devzeroty·2023년 8월 2일
0

Partial<Type>

가장 처음으로 살펴볼 유틸리티 타입은 Partial 타입입니다. Partial은 부분적인 또는 일부분의 라는 뜻으로 특정 객체 타입의 모든 프로퍼티를 선택적 프로퍼티로 변환합니다. 따라서 기존 객체 타입에 정의된 프로퍼티들 중 일부분만 사용할 수 있도록 도와주는 타입입니다.

예제

interface Todo {
  title: string;
  description: string;
}
 
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}
 
const todo1 = {
  title: "organize desk1",
  description: "clear clutter",
};
 
const todo2 = updateTodo(todo1, {
  description: "throw out trash",
});

console.log(todo2);

결과

[LOG]: {
  "title": "organize desk1",
  "description": "throw out trash"
} 

언제 사용하나?

이번에는 간단한 블로그 플랫폼의 일부를 직접 구현한다고 가정해 보겠습니다. 일단 다음과 같이 게시글 하나를 표현하는 타입을 먼저 선언합니다.

  interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

다음으로 임시 저장 기능이 필요하다고 가정하겠습니다. 그럼 다음과 같이 임시 저장된 게시글을 변수로 저장할 수 있어야 합니다.

  interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const draft: Post = { // tags 프로퍼티가 없음
  title: "제목은 나중에 짓자...",
  content: "초안...",
};

그런데 이때 문제가 발생합니다. 위와 같이 게시글의 일부 정보가 아직 설정되어 있지 않은 임시 저장 게시글의 경우에도 변수에 저장할 수 있어야 하는데 해당 변수를 Post 타입으로 정의하면 오류가 발생하게 됩니다.
그렇다고 임시 저장 게시글 기능을 위해 Post 타입의 모든 프로퍼티를 선택적 프로퍼티로 설정하는 것도 곤란합니다. 진짜 작성이 완료되어 화면에 렌더링 될 게시글들은 이 모든 프로퍼티를 진짜 다 가지고 있어야 하기 때문입니다.
이럴 때에는 어떻게 해야 할까요?

Partial 타입으로 문제 해결하기
이런 상황에 다음과 같이 Partial 유틸리티 타입을 이용하면 좋습니다.

interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const draft: Partial<Post> = {
  title: "제목 나중에 짓자",
  content: "초안...",
};

Partial 타입은 타입 변수 T로 전달한 객체 타입의 모든 프로퍼티를 다 선택적 프로퍼티로 변환합니다. 따라서 Partial 타입은 모든 프로퍼티가 선택적 프로퍼티가 된 Post 타입과 같습니다.

Partial 구현하기

그럼 이번에는 Partial 유틸리티 타입을 직접 구현해 보겠습니다.
천천히 하나씩 만들어보겠습니다. 일단 하나의 타입 변수 T를 사용하는 제네릭 타입인 것 만은 확실합니다.

type Partial<T> = any;

다음으로는 T에 할당된 객체 타입의 모든 프로퍼티를 선택적 프로퍼티로 바꿔줘야 합니다. 기존 객체 타입을 다른 타입으로 변환하는 타입은 맵드 타입이었습니다. 따라서 맵드 타입을 이용해 다음과 같이 수정합니다.

type Partial<T> = {
  [key in keyof T]?: T[key];
};

이렇게 Partial 타입 구현을 마쳤습니다.

profile
개발자

0개의 댓글