Utility types

Donggu(oo)·2023년 11월 17일

TypeScript

목록 보기
4/8
post-thumbnail

0. Utility types


  • TypeScript는 공통 타입 변환을 용이하게 하기 위해 유틸리티 타입을 제공한다.

  • 유틸리티 타입은 전역으로 사용 가능하다.

1. Partial<T>

  • 프로퍼티를 선택적(부분적)으로 만드는 타입을 구성한다. 주어진 타입의 모든 하위 타입 집합을 나타내는 타입을 반환한다.

  • 아래 예제 코드에서 updateTodo 함수 호출 시 title을 제외한 description 호출하여 사용이 가능한 것을 확인할 수 있다.

interface Todo {
  title: string;
  description: string;
}

const updateTodo = (todo: Todo, fieldsToUpdate: Partial<Todo>) => {
  return { ...todo, ...fieldsToUpdate };
};

const todo1 = {
  title: 'organize desk',
  description: 'clear clutter',
};

const todo2 = updateTodo(todo1, {
  description: 'throw out trash',
});

2. Readonly<T>

  • 프로퍼티를 읽기 전용(readonly)으로 설정한 타입을 구성한다.

  • 아래 예제 코드에서 todo 객체의 프로퍼티에 재할당을 방지하기 위해 Readonly 타입을 사용했다.

interface Todo {
  title: string;
}

const todo: Readonly<Todo> = {
  title: 'Delete inactive users',
};

todo.title = 'Hello';  // Error: Cannot as sign to 'title' because it is a read-only property

3. Record<K, T>

  • 프로퍼티의 집합 K로 타입을 구성한다. 타입의 프로퍼티들을 다른 타입에 매핑 시키는데 사용한다.

  • 아래 예제 코드를 보면 변수 x는 Record 타입 Page, PageInfo로 구성되어 있다. home의 value를 보면 object subTitle을 선언했는데 PageInfo에는 subTitle이라는 프로퍼티가 없으므로 에러가 발생하게 된다.

  • 또한 Page에는 'home', 'about', 'contact'라는 변수들만 선언되어 있는데 변숫값으로 main을 선언했기 때문에 마찬가지로 에러가 발생하는 것을 확인할 수 있다.

interface PageInfo {
  title: string;
}

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

const x: Record<Page, PageInfo> = {
  about: { title: 'about' },
  contact: { title: 'contact' },
  home: { subTitle: 'home' },  // Error: '{subTitle: string}' is not assignable
  main: { title: 'home' },  // Error: main is not assignable to type 'Page'
};

참고

4. Pick<T, K>

  • 모든 프로퍼티 중에서 선택한 K의 집합만으로 타입을 구성한다.

  • 아래 예제 코드를 보면 타입 TodoPreview는 Todo 인터페이스의 title과 completed 프로퍼티만 선택해 타입을 구성했다. 하지만 todo 변수에 선택하지 않은 description key, value를 선언했기 때문에 에러가 발생하는 것을 확인할 수 있다.

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick<Todo, 'title' | 'completed'>;

const todo: TodoPreview = {
  title: 'Clean room',
  completed: false,
  description: 'description',  // Error: 'description' is not assignable to type
};

5. Omit<T, K>


  • Omit은 Pick 과는 반대로 모든 프로퍼티 중에서 선택한 K를 제거한 타입을 구성한다.

  • 아래 예제 코드를 보면 타입 TodoPreview는 Todo 인터페이스의 description 프로퍼티를 선택하여 제거했다. 따라서 todo 변수에 제거된 description 변수를 선언하면 에러가 발생하는 것을 확인할 수 있다.


interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Omit<Todo, 'description'>;

const todo: TodoPreview = {
  title: 'Clean room',
  completed: false,
  description: 'description',  // Error: 'description' is not assignable to type
};

6. Exclude<T, U>


  • T에서 U에 할당할 수 있는 모든 속성을 제외한 타입을 구성한다. 즉, T에서 U를 제외한 타입만 사용할 수 있다.

  • 아래 예제 코드에서 타입 T0은 a, b, c 프로퍼티 중 a를 제외했기 때문에 b와 c 타입만 사용 가능한 것을 확인할 수 있다.

type T0 = Exclude<'a' | 'b' | 'c', 'a'>;  // 'b' | 'c'

type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>;  // 'C'

type T2 = Exclude<string | number | (() => void), Function>;  // string | number

7. Extract<T, U>


  • T에서 U에 할당할 수 있는 모든 속성을 추출하여 타입을 구성한다. 즉 T와 U에 모두 존재하는(겹치는) 타입만 사용할 수 있다.

  • 아래 예제 코드에서 타입 T0은 a, b, c 프로퍼티 중 a와 f를 추출했는데 f 타입은 존재하지 않기 때문에 a 타입만 구성이 되는 것을 확인할 수 있다.

type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>;  // 'a'

type T1 = Extract<string | number | (() => void), Function>;  // '() => void'

8. NonNullable<T>


  • null과 undefined를 제외한 나머지 타입만 사용할 수 있게 구성하는 타입이다.
type T0 = NonNullable<string | number | undefined>;  // string | number

type T1 = NonNullable<string[] | null | undefined>;  // string[]

9. Parameters<T>


  • 함수 타입 T의 매개변수 타입들의 튜플 타입을 구성한다.
declare function f1(arg: { a: number; b: string }): void;

type T0 = Parameters<() => string>;  // []
type T1 = Parameters<(s: string) => void>;  // [string]
type T2 = Parameters<<T>(arg: T) => T>;  // [unknown]
type T3 = Parameters<typeof f1>;  // [{a: number, b: string}]
type T4 = Parameters<any>;  // unknown[]
type T5 = Parameters<never>;  // never
type T6 = Parameters<string>;  // 오류
type T7 = Parameters<Function>;  // 오류

10. ConstructorParameters<T>


  • 생성자 함수 타입의 모든 매개변수 타입을 추출한다. 모든 매개변수 타입을 가지는 튜플 타입(T가 함수가 아닌 경우 never)을 생성한다.

  • 아래 예제 코드의 T12 타입은 인터페이스 I1 ConstructorParameters 타입을 선언했다. 인터페이스 I1의 매개변수는 string argument 하나만 존재하므로 string 값을 가지는 튜플 타입을 구성하는 것을 확인할 수 있다.

  • 따라서 function f1에 타입 T12를 선언했을 때 a 변수는 index 1을 가지고 있지 않기 때문에 a[1]을 선언했을 때 타입 에러가 발생하게 된다.

type T10 = ConstructorParameters<ErrorConstructor>;  // [(string | undefined)?]
type T11 = ConstructorParameters<FunctionConstructor>;  // string[]
type T12 = ConstructorParameters<RegExpConstructor>;  // (string, [string | undefined]?)

interface I1 {
  new (args: string): Function;
}
type T12 = ConstructorParameters<I1>;  // [string]

function f1(a: T12) {
  a[0];
  a[1];  // Error: Tuple type '[args: string]' of length '1' has no element at index '1'.
}

11. ReturnType<T>


  • 함수 T의 반환 타입으로 구성된 타입을 생성한다.
declare function f1(): { a: number; b: string };

type T0 = ReturnType<() => string>;  // string
type T1 = ReturnType<(s: string) => void>;  // void
type T2 = ReturnType<(<T>() => T)>;  // {}
type T3 = ReturnType<(<T extends U, U extends number[]>() => T)>;  // number[]
type T4 = ReturnType<typeof f1>;  // {a: number, b: string}
type T5 = ReturnType<any>;  // any
type T6 = ReturnType<never>;  // any
type T7 = ReturnType<string>;  // 오류
type T8 = ReturnType<Function>;  // 오류

12. Required<T>


  • T의 모든 프로퍼티가 필수로 설정된 타입을 구성한다.

  • 아래 예제 코드를 보면 인터페이스 Props는 a와 b 프로퍼티를 옵셔널로 설정했지만 유틸리티 타입을 Required로 설정했기 때문에 b 프로퍼티를 설정하지 않아서 에러가 발생하는 것을 확인할 수 있다.

interface Props {
  a?: number;
  b?: string;
}

const obj: Props = { a: 5 };

const obj2: Required<Props> = { a: 5 };  // Error: Property 'b' is missing in type '{a: number}'
profile
FE Developer

0개의 댓글