프로그래밍프론트엔드/풀스택 개발자

타입스크립트에서 ReturnType<T> 타입은 어떻게 작동하며, 함수의 반환 값 타입을 수동으로 추론하는 것과 어떤 차이가 있습니까? 그리고 사용 시 어떤 위험과 이점이 있습니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문의 배경

타입스크립트의 발전과 함께, 특히 서로 관련된 함수가 많은 대규모 프로젝트에서 함수의 반환 값 타입을 자동으로 추출할 필요성이 생겼습니다. 이를 위해 표준 라이브러리에서 타입스크립트 2.8 버전부터 도입된 유틸리티 타입 ReturnType<T>가 있습니다.

문제

대규모 복잡한 프로젝트에서는 각 함수의 반환 값 타입을 수동으로 지정하고 시그니처를 변경할 경우 타입의 불일치를 쉽게 발생시킬 수 있습니다. 또한 함수가 복잡한 구조를 반환하는 경우, 모든 사용 위치에서 반환 타입을 수동으로 동기화하는 것이 항상 쉬운 것은 아닙니다.

해결책

유틸리티 타입 ReturnType<T>는 함수의 반환 타입을 자동으로 추출하고, 코드의 어느 위치에서든 함수 호출의 결과를 타입 지정하는 데 사용할 수 있습니다. 이는 타입 인프라의 수동 유지 관리를 줄이고, 기술된 반환 값 타입과 실제 반환 값 타입 간의 불일치로 인한 오류를 최소화합니다.

코드 예:

function createUser(name: string, age: number) { return { name, age, created: new Date() }; } type User = ReturnType<typeof createUser>; // User: { name: string; age: number; created: Date; }

주요 특징:

  • 함수의 반환 값 타입을 자동으로 추출하여 코드 중복을 없앱니다.
  • 함수 시그니처나 반환 값 구조 변동 시 오류 발생 가능성을 줄입니다.
  • 함수 오버로드와는 작동하지 않으며, 오직 일반(광범위한) 반환 타입만 추출합니다.

꼬리 질문.

ReturnType을 클래스 메서드와 함께 사용할 수 있나요?

네, 그러나 문맥을 기억하는 것이 중요합니다: 메서드가 객체의 함수 속성인 경우, ReturnType<obj['메서드']>를 사용해야 합니다.

코드 예:

class MyClass { foo(x: number) { return x * 2; } } type FooReturn = ReturnType<MyClass['foo']>; // 타입 오류! // 이렇게 해야 합니다: type FooReturn = ReturnType<(x: number) => number>; // number // 또는 메서드를 함수로 분리: const obj = new MyClass(); type FooReturn2 = ReturnType<typeof obj.foo>;

void/never 타입을 가진 함수에 대해 ReturnType은 무엇을 반환합니까?

void 타입으로 선언된 함수에 대해 ReturnType은 void를 반환합니다. never 타입의 경우에는 never를 반환합니다.

코드 예:

function doNothing(): void {} type Result = ReturnType<typeof doNothing>; // void

ReturnType은 함수 오버로드와 함께 작동합니까?

아니요, ReturnType은 "구현"의 반환 타입만 추출하며 모든 오버로드의 반환 타입을 추출하지 않습니다. 오버로드가 여러 개일 경우에는 기술된 구현 타입이 사용됩니다.

코드 예:

function func(x: number): number; function func(x: string): string; function func(x: any): any { return x } type RT = ReturnType<typeof func>; // any

타입 오류 및 안티 패턴

  • 오버로드된 함수와 함께 ReturnType을 사용하면 예기치 않은 타입이 발생할 수 있습니다.
  • ReturnType은 Promise의 반환 타입을 계산하지 않으므로 Awaited 또는 수동 작업이 필요합니다.
  • 함수의 논리를 변경할 때 다른 종속 코드 부분을 업데이트하지 않고 ReturnType에만 전적으로 의존하게 됩니다.

실제 사례

부정적인 사례

프로젝트에서 함수가 반환하는 객체의 반환 타입을 수동으로 선언합니다. 함수가 변경되면 타입이 업데이트되지 않아 런타임에 호출이 실패합니다.

장점:

  • 타입을 쉽게 읽을 수 있으며 수동으로 조정할 수 있습니다.

단점:

  • 빠르게 구식이 되어 타입과 실제 API 간의 "드리프팅"이 발생합니다.

긍정적인 사례

함수에 의해 반환되는 값을 사용하는 모든 곳에서 ReturnType으로 전환합니다. 변경이 있을 경우 타입이 항상 최신 상태로 유지됩니다.

장점:

  • 최소한의 중복, 실제 구현과의 타입 일치를 보장합니다.

단점:

  • 초보자들에게 타입의 마법을 이해하기 어려울 수 있습니다.