ReturnType과 Typeof Operator

SooSoo·2021년 10월 8일
3

공부정리

목록 보기
4/7

동기

Typescript와 관련된 문제를 해결하다가 의문점이 든 부분에 대해 조사해보았다.

ReturnType을 직접 구현해보고 있었는데

ReturnType<typeof fn>

위와 같은 형태로 많이 사용했다.

ReturnType의 정확한 동작과 typeof를 써야하는 이유에 대해 의문이 들어 찾아보았다.

조사 내용

ReturnType은 다음과 같이 직접 정의할 수 있다.

/**
 * Obtain the return type of a function type
 */
//typescript에서 정의해둔 것을 그대로 가져왔다.
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

infer 키워드가 쓰인 것이 낯설게 느껴진다.

타입스크립트 공식문서에서는 infer의 사용법을 다음과 같이 정의하고 있다.
필요한 타입을 추론하여 사용할 수 있다는 내용이다.

Type inference in conditional types

Within the extends clause of a conditional type, it is now possible to have infer declarations that introduce a type variable to be inferred. Such inferred type variables may be referenced in the true branch of the conditional type. It is possible to have multiple infer locations for the same type variable.

위의 식에 적용해보자면,
제네릭 T는 함수형태의 type을 extends하는데, 그 함수의 리턴값의 type을 추론가능하다면 그 type을 반환해준다는 의미이다.

그런데, 보통 사용처에서는 다음과 같이 쓰인다.
리덕스 공식문서에서 가져온 예시이다.

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>

ReturnType을 사용할 때 제네릭에 typeof 키워드를 사용하는 이유는 무엇일까?

다시 타입스크립트 공식문서를 참고하여 이유를 알아보았다.

Remember that values and types aren’t the same thing. To refer to the type that the value f has, we use typeof:

제네릭에는 타입을 넣어주어야한다.
공식문서에 적힌 내용대로 제네릭에 < f(n) > 형태로 넣어주는 것은 제네릭에 값을 넣어주는 것이다.
따라서 <typeof f(n)>으로 써주는 것이 옳은 사용법이라고 할 수 있다.

필자는 리액트에서 리덕스를 사용하면서 ReturnType을 관성적으로 많이 사용했었다.

적용

벨로퍼트님의 Redux Typescript 소개글에도 다음과 같은 문법을 볼 수 있다.

export const increase = () => ({ type: INCREASE });
export const decrease = () => ({ type: DECREASE });
export const increaseBy = (diff: number) => ({
  type: INCREASE_BY,
  payload: diff
});

type CounterAction =
  | ReturnType<typeof increase>
  | ReturnType<typeof decrease>
  | ReturnType<typeof increaseBy>;

이전까지는 큰 의미를 두지않고 사용했었는데, 의미를 좀 더 명확히 할 수 있을 것 같다.

reducer로 전달되는 Action은 Action 생성 함수에서 반환된다.
따라서 Action의 타입은 Action 생성함수의 ReturnType으로 정의하는 것이 당연하다.

profile
꾸준히

0개의 댓글