Typescript Infer 1편 : infer 란?

프디·2025년 4월 13일

Typescript infer

목록 보기
1/5

1. 왜 infer가 필요한가?

타입스크립트를 쓰다 보면 이런 상황이 생긴다:

function getUser() {
  return {
    id: 1,
    name: 'Alice',
  };
}

이 함수의 반환 타입을 추론하고 싶은데, typeof getUser만으로는 매개변수와 반환 타입을 각각 얻을 수 없다. 이럴 때 ReturnType<typeof getUser>를 쓰면 "반환 타입"만 쏙 뽑아올 수 있다. 하지만 이건 내장 유틸리티 타입이니까 가능한 일이다.

그럼 이렇게 묻고 싶다:

그 유틸리티 타입은 어떻게 만들어진 걸까?

답은 간단하다. infer 덕분이다.


2. infer 키워드는 정확히 무엇인가?

infer는 조건부 타입(T extends ... ? ... : ...) 안에서만 사용할 수 있는 키워드다.

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

이 구문에서 T가 함수 타입이라면 infer R을 통해 해당 함수의 반환 타입을 추론한다. 추론한 타입은 조건식의 true 분기에서 사용할 수 있게 된다.

즉, 위 표현은 이렇게 읽을 수 있다:

T가 함수 타입이라면, 그 함수의 반환 타입을 R이라고 하자. 그러면 전체 타입은 R이다.
만약 함수 타입이 아니라면 any로 처리하자.


3. ReturnType를 통해 살펴보는 infer의 기본 구조

function fn(num: number) {
  return num.toString(); 
}

type Result = ReturnType<typeof fn>; // string

typeof fn(num: number) => string이라는 함수 타입이다. 이 타입을 T extends (...args: any[]) => infer R에 대입하면, Rstring으로 추론된다. 그래서 ReturnType<typeof fn>은 결국 string이 되는 것이다.

infer R은 타입스크립트가 타입 안의 일부를 추론해서 R이라는 이름으로 사용할 수 있게 해주는 기능이다.
즉, 복잡한 타입 구조 안에서 우리가 원하는 부분을 추출해서 변수처럼 다루게 해준다.


4. 직접 구현해보자

이제 우리도 ReturnType을 직접 만들어보자.

type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getValue(x: number) {
  return x > 0 ? 'yes' : 'no';
}

type ValueReturn = MyReturnType<typeof getValue>; // "yes" | "no" => string

MyReturnType은 실제 ReturnType과 거의 같다. infer R로 반환 타입을 추론하고, 없으면 never을 주도록 구성했다.


우리가 직접 'string', 'number' 같은 타입을 일일이 써주지 않아도,
TypeScript가 타입의 구조를 보고 적절한 부분을 알아서 추론해주고,
그걸 infer라는 이름으로 임시 저장해서 사용할 수 있게 해주는 것.
바로 그게 infer 키워드의 핵심이다.

profile
프론트엔드개발자인디

0개의 댓글