타입스크립트에서 함수 입출력을 타입화 하기

박재훈·2022년 11월 26일
0

Node.js

목록 보기
1/3

타입스크립트에서는 별걸 다 타입으로 만들 수 있다.

대표적으로 함수의 파라미터와 반환값의 타입을 얻어낼 수 있다.

export type ArgumentTypes<F extends (...a: any[]) => any> = F extends (
  ...args: infer A
) => any
  ? A
  : never;

먼저 파라미터를 타입화 하면 위와 같다. 하나하나씩 자세히 설명하자면,

  • <F extends (...a: any[]) => any>
    • 제네릭으로 모든 함수를 받는 것을 의미한다. 타입스크립트의 함수들 중 (...a: any[]) => any를 만족하지 않는 것은 없기 때문에 그렇다. <F extends Function> 같은 방식도 가능하다.
  • F extends (...args: infer A) => any ? A : never;
    • F는 제네릭으로 입력 받은 함수이고, 그 함수가 (...args: infer A) => any 형태를 만족시켜야 한다. 이 말인즉슨, F의 파라미터의 형태가 A로 추론될 수 있어야 한다는 것이고, 곧 파라미터의 형태가 A와 같아야 한다는 것이다. 이후 삼항연산자로 이어지지만 never에 도달할 일은 없다.

이걸 실제로 써보면 다음과 같이 된다.

function test(n: number, b: boolean): string {
  return `${n}.${b}`;
}

const a: ArgumentTypes<typeof test> = [10, true];
test(...a);

함수의 타입들을 튜플 형태로 가져오게 되며, 그렇기에 전개연산자를 통해 함수에 파라미터로 줄 수도 있다.

또한 반환도 타입으로 지정할 수 있다.

export type ReturnType<F extends (...a: any[]) => any> = F extends (
  ...args: any[]
) => infer R
  ? R
  : never;

아까의 ArgumentTypes와의 차이점은 infer의 위치뿐이다. 기존에는 파라미터 ...argsinfer로 지정했던 것이 이번에는 리턴 타입을 지정하는 부분(=> infer R)으로 바뀌었다.
알아챘겠지만 리턴값이 R과 동일해야 한다는 것을 의미한다. 마찬가지로 never에는 도달할 일이 없다.

function test(n: number, b: boolean): string {
  return `${n}.${b}`;
}

const r: ReturnType<typeof test> = "good";

위처럼 사용될 수 있다.

enum도 타입화 할 수 있다.

export type Enum<E> = Record<keyof E, E[keyof E]>;

Record{[key]: [value]} 형태의 오브젝트를 의미한다. 따라서 여기에서는 키 타입이 keyof E이고 값 타입이 E[keyof E]가 되는 것이다.
keyof E라고 한다면 enum의 키값들을 의미한다. 또한 E[keyof E]는 제네릭으로 받은 E라는 enum에 대해 해당 키를 가지고서 얻은 값을 의미한다.

enum Status {
  Pending = 0,
  Done = 1,
}

위와 같은 간단한 enum이 있다고 했을 때,

const a: Enum<Status> = Status.Done;

이런 식으로 이용이 가능하다.

이것들을 도대체 어디에 쓰냐고 물어볼 수 있는데 의외로 필요한 부분들이 가끔씩 생긴다.

profile
코딩 좋아합니다

0개의 댓글