gloriaJun / til

Lessoned Learned
3 stars 0 forks source link

Typescript의 기본 유틸 타입 #115

Open gloriaJun opened 3 years ago

gloriaJun commented 3 years ago

Partial

Patial 타입은 제네릭 타입의 T 타입의 Public Property 들에 대하여 기존의 타입은 유지하되, 각각의 Property 들을 Optional 타입으로 변경해준다.

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

// ex)
interface Todo {
    id: string;
    text: string;
    isDone: boolean;
}

type OptionalTodo1 = Partial<Todo>;

// OptionalTodo1 와 OptionalTodo2 는 동일한 타입이다.
interface OptionalTodo2 {
    id?: string;
    text?: string;
    isDone?: boolean;
}

Required

type Required<T> = {
    [P in keyof T]-?: T[P];
};

// ex)
interface OptionalTodo {
    id: string;
    text?: string;
    isDone?: boolean;
}

// 타입 Todo1과 타입 Todo2 는 동일한 타입이다.
type Todo1 = Required<OptionalTodo>;

interface Todo2 {
    id: string;
    text: string;
    isDone: boolean;
}

Readonly

주어진 제네릭 타입 T의 모든 프로퍼티가 readonly 속성을 갖도록 변경한다.

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

Pick<T, K>

주어진 첫번째 제네릭 타입 T 내에서 Union 타입 K에 대한 프로퍼티에 대한 타입들을 뽑아낸다.

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

// ex)
interface Todo {
  id: string;
  title: string;
  isDone: boolean;
};

// TodoWithIdAndTitle 타입과 PickedTodo 타입은 동일한 타입이다.
type TodoWithIdAndTitle = Pick<Todo, 'id' | 'title'>;

interface PickedTodo {
  id: string;
  title: string;
}

Record

Record 타입은 총 두개의 제네릭 타입을 받을 수 있다. 첫번째 제네릭 타입 K은 프로퍼티 타입으로, 두번째 제네릭 타입 T은 값의 타입으로 사용된다.

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

// ex)
type IFooBar = {
  foo: string;
  bar: string;
};

type IHelloWorld = 'hello' | 'world';

const x: Record<IHelloWorld, IFooBar> = {
  hello: {
    foo: 'foo',
    bar: 'bar'
  },
  world: {
    foo: 'foo',
    bar: 'bar'
  }
}

Exclude

Exclude 타입은 2개의 제네릭 타입을 받을 수 있으며, 조건부 타입(Conditional type)을 이용하여 타입을 정의 한다. 두번째 제네릭 타입에 대하여 첫번째 제네릭 타입이 할당 가능한 타입(Assignable)인지를 여부를 판단하여 할당 가능한 타입을 제외한 나머지 타입들을 이용하여 타입을 정의한다.

type Exclude<T, U> = T extends U ? never : T;

Extract

Exclude 타입과 반대의 타입이다.


type Extract<T, U> = T extends U ? T : never;

Omit

Omit 타입은 두개의 제네릭 타입을 받으며 첫번째 제네릭 타입 T에 대하여 두번째 제네릭 타입 K의 값을 제외한 나머지 값을 반환합니다.


type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

// ex)
interface Todo {
  id: string;
  title: string;
  isDone: boolean;
}
type TodoWithOutId = Omit<Todo, "id">;
// TodoWithOutId의 타입은 아래의 인터페이스와 일치한다.
interface TodoWithOutId {
    title: string;
    isDone: boolean;
}

NonNullable

NonNullable 유틸타입은 주어진 제네릭 타입 안에서 null이나 undefined을 제거한다.


type NonNullable<T> = T extends null | undefined ? never : T;

// ex)
type Todo = {
  id: string;
  title: string;
  isDone: boolean;
}

type NullableTodos = null | undefined | Todo[];

type Todos = NonNullable<NullableTodos>;
/**
 * type Todos = Todo[];
 */

ReturnType

ReturnType 타입은 주어진 제네릭 타입 T의 return type을 할당한다.

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

// ex
interface IPayload {
  foo: string;
  bar: string;
}

const fooBarCreator = () => ({
    foo: "foo", bar: "bar"
});

type IFooBarCreator = ReturnType<typeof fooBarCreator>;

Reference