Typescript: Utility types

coolchaem·2021년 12월 7일
1

TypeScript

목록 보기
1/3

typescript로 개발하다보면 다음과 같이 object literal을 사용하고 싶을 떄가 있으나, type definition이 없어 권장되지 않는 것을 알았다.

const tmpArr = {}; //error! key랑 value가 any type이다.

const arr = [4, 5, 3, 2, 3, 4];
// typedef를 넣으면 이렇게 사용가능하다.
const tmpArr: { [key: number]: boolean } = {};
arr.forEach((num: number) => (tmpArr[num] = true));

근데 Tyepscript에서 Utility Types를 제공하는 것을 발견하여 차이가 있을까하여 정리해보았다. typescript documentation을 읽어보니 object literal을 대체하는 것이라기보다 타입 변환에 목적을 둔다고 한다.

Record

  • Record<Keys, Type>
    • property key는 Keys 집합에서 만들어질 수 있으며, property value는 Type에 속한다 라는 단순한 util type이다.
    • 그럼 object literal 예시를 다음처럼 바꿀 수 있다. 프리미티브 타입으로 keys와 type을 설정하면 동일해진다.
const arr = [4, 5, 3, 2, 3, 4];
const tmpArr: Record<number, boolean> = {};
arr.forEach((num: number) => (tmpArr[num] = true));

// 실제 Record 레퍼런스를 타고가 코드를 보면 다음과 같다.
type Record<K extends keyof any, T> = {
    [P in K]: T;
};
  • 그리고 아래처럼 사용하는 것이 일반적인 상황으로 보인다. 반복적으로 type이 중복이된다면 아래가 깔끔할 것이다.
interface PageInfo {
  title: string;
}

type Page = 'home' | 'about' | 'contact';

const nav: Record<Page, PageInfo> = {
  about: { title: 'about' },
  contact: { title: 'contact' },
  home: { title: 'home' },
};

// 참고로 이건 불가능하다!
// index signature에 object는 올 수 없다는 이야기가 나온다.
const badNav: { [key: Page]: PageInfo } = {
  about: { title: 'about' },
  contact: { title: 'contact' },
  home: { title: 'home' },
};

Partial

  • Partial<Type>
    • Type 집합에서 프로퍼티를 선택해서 타입을 생성할 수 있다.
interface PageInfo {
  title: string;
  about: string;
  contact: string;
  home: string;
}

const nav2: Partial<PageInfo> = {
  about: 'about',
  home: 'home',
};

Required

  • Required<Type>
    • Type 집합에서 모든 프로퍼티를 가져야 하는 타입을 생성한다.
interface PageInfo {
  title?: string;
  about: string;
  contact: string;
  home: string;
}

// 그래서 page info의 title이 undefined가 가능하지만 이 경우엔 error 가 난다!
const nav2: Required<PageInfo> = {
  // Property 'title' is missing in type
  // title을 꼭 추가해야 한다.
  about: 'about',
  contact: 'contact',
  home: 'home',
};

Readonly

  • Readonly<Type>
    • Type 집합의 모든 프로퍼티를 읽기 전용으로 타입을 생성한다.
interface PageInfo {
  about: string;
  home: string;
}

const nav2: Readonly<PageInfo> = {
  about: 'about',
  home: 'home',
};

// error
// Cannot assign to 'home' because it is a read-only property.
nav2.home = 'error를 내보자';

Pick

  • Pick<Type, Keys>
    • Type 집합에서 Keys 프로퍼티만 선택해 타입을 만든다고 한다.
    • 규모가 크다보면 나눠진 로직에서 일회성으로 type을 선언하여 기존 type 값으로 사용할 때가 종종 있는데, Pick이라는 것을 사용하면 편리할 것으로 보인다.
interface PageInfo {
  title: string;
  about: string;
  contact: string;
  home: string;
}

const nav2: Pick<PageInfo, 'about' | 'home'> = {
  about: '1',
  home: '2',
};

Omit

  • Omit<Type, Keys>
    • Pick 반대로 제외할 수 있다고 한다.

interface PageInfo {
  title: string;
  about: string;
  contact: string;
  home: string;
}

const nav2: Omit<PageInfo, 'title' | 'contact'> = {
  about: '1',
  home: '2',
};

이외 여러가지 utility type이 존재해서 프로그램 특성에 따라 자주 사용하는 타입 변환 방식의 util을 사용하면 좋을 것 같다.

profile
Front-end developer

0개의 댓글