함수의 반환 유형 얻기


104

다음과 같은 기능이 있습니다.

function test(): number {
    return 42;
}

다음을 사용하여 함수 유형을 얻을 수 있습니다 typeof.

type t = typeof test;

여기에, t있을 것이다 () => number.

함수의 반환 유형을 얻는 방법이 있습니까? 내가 좋아하는 것 t으로 number대신 () => number.


2
아니, 어쨌든 typeof는 아닙니다. typeof는 "함수"만 반환합니다 ( 내 대 / 소문자가 잘못되었을 수 있음 ).
이고르

이것이 가능 해지면 좋을 것입니다. 때로는 함수에서 유형을 푸시 할 때 유형을 정의하며이 구조를 캡처하는 (좋은) 방법이 없습니다.
Jørgen Tvedt

답변:


167

편집하다

TypeScript 2.8부터는 공식적으로 ReturnType<T>.

type T10 = ReturnType<() => string>;  // string
type T11 = ReturnType<(s: string) => void>;  // void
type T12 = ReturnType<(<T>() => T)>;  // {}
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>;  // number[]

자세한 내용은 Microsoft / TypeScript에 대한 이 풀 요청을 참조 하십시오.

TypeScript는 굉장합니다!


구식 해킹

Ryan의 대답은 더 이상 작동하지 않습니다. 그러나 나는 부당하게 기뻐하는 해킹으로 그것을 수정했습니다. 보다:

const fnReturnType = (false as true) && fn();

false리터럴 값 으로 캐스트 하여 작동 true하므로 유형 시스템은 반환 값이 함수의 유형이라고 생각하지만 실제로 코드를 실행하면 false.


53
맙소사, 끔찍합니다.
John Weisz

흐름 : const DUMMY = ((null : any) : Object) && fn () export type Type = typeof DUMMY
David Xu

2.8을 설치하고 다음 오류가 발생하는 이유는 Cannot find name 'ReturnType'무엇입니까? vscode 사용
NSjonas

1
@NSjonas 다른 버전을 사용하도록 vscode에 알려야합니다. 오른쪽 하단에 상태 표시 줄이있는 것 같습니다.
Meirion Hughes

13
나는해야했다 ReturnType<typeof fn>(답 ReturnType<fn>은 충분하다는 것을 의미한다 ).
spacek33z

52

TypeScript 2.8에서 가장 쉬운 방법 :

const foo = (): FooReturnType => {
}

type returnType = ReturnType<typeof foo>;
// returnType = FooReturnType

5

아래 코드는 함수를 실행하지 않고 작동합니다. react-redux-typescript 라이브러리 ( https://github.com/alexzywiak/react-redux-typescript/blob/master/utils/redux/typeUtils.ts ) 에서 가져 왔습니다.

interface Func<T> {
    ([...args]: any, args2?: any): T;
}
export function returnType<T>(func: Func<T>) {
    return {} as T;
}


function mapDispatchToProps(dispatch: RootDispatch, props:OwnProps) {
  return {
    onFinished() {
      dispatch(action(props.id));
    }
  }
}

const dispatchGeneric = returnType(mapDispatchToProps);
type DispatchProps = typeof dispatchGeneric;

4

이를 수행하는 방법이 없습니다 ( 이를 추가하는 작업 항목 추적에 대해서는 https://github.com/Microsoft/TypeScript/issues/6606 참조 ).

일반적인 해결 방법은 다음과 같이 작성하는 것입니다.

var dummy = false && test();
type t2 = typeof dummy;

3
이 해결 방법이 더 이상 작동하지 않을 것이라고 생각합니다. 제어 흐름 기반 유형 분석 때문일 수 있습니다.
JKillian

3
당신이 맞다 @JKillian 쉽게와 타이프 라이터를 속일 수 있지만,이 예제는 더 이상 작품을 제안하지 !1대신 false- typescriptlang.org/play/...
DanielM

3

편집 : TS 2.8에서는 더 이상 필요하지 않습니다! ReturnType<F>반환 유형을 제공합니다. 수락 된 답변을 참조하십시오.


내가 사용하는 이전 답변 중 일부에 대한 변형으로 strictNullChecks추론 체조 에서 작동 하고 약간 숨 깁니다.

function getReturnType<R>(fn: (...args: any[]) => R): R {
  return {} as R;
}

용법:

function foo() {
  return {
    name: "",
    bar(s: string) { // doesn't have to be shorthand, could be `bar: barFn` 
      return 123;
    }
  }
}

const _fooReturnType = getReturnType(foo);
export type Foo = typeof _fooReturnType; // type Foo = { name: string; bar(s: string): number; }

그것은 않습니다 부르는 getReturnType기능을하지만, 하지 않는 원래의 함수를 호출합니다. 사용 하는 호출을 막을 수 있지만 IMO는 더 혼란 스럽습니다.getReturnType(false as true) && getReturnType(foo)

이 방법을 정규 표현식 찾기 / 바꾸기와 함께 사용하여 원래 JS에서 이와 같이 작성된 ~ 1500 팩토리 함수가있는 오래된 Angular 1.x 프로젝트를 마이그레이션하고 Foo모든 용도에 기타 유형을 추가했습니다. 찾을 것이다. :)


감사! 슬프지만이 정도의 말이 필요하지만 적어도 작동합니다!
ecmanaut

@ecmanaut 우리는 더 이상 이것을 필요로하지 않습니다! TS 2.8에서는 ReturnType<F>함수 반환 유형을 가져 오는 데 사용할 수 있습니다 . :)
Aaron Beall

여기에 대한 답변은 질문의 예제 기판과 크게 다르므로 함수의 반환 된 유형 인 유형을 생성하는 방법을 파악하기 어렵습니다 test. 이 답변은 이름 test을 바꾸는 데 더 유용한 답변 중 하나였습니다 foo(그리고 킥을 위해 더 복잡한 반환 유형을 생성하는 것을 인정합니다). 원래 예제에 적용하는 방법을 이미 알고 있다면 수락 된 답변과 귀하의 의견이 모두 훌륭 할 것입니다. (여기는 늦은 밤이며 전체 ReturnType 예제의 구문이 어떻게 생겼는지 즉시 알 수는 없습니다.)
ecmanaut

1

문제의 함수가 사용자 정의 클래스의 메서드 인 경우 리플 렉트 메타 데이터 와 함께 메서드 데코레이터 를 사용 하여 런타임에 반환 유형 (생성자 함수)을 결정할 수 있습니다 (그리고이를 사용하여 적합하다고 생각하는대로 수행).

예를 들어 콘솔에 기록 할 수 있습니다.

function logReturnType(
    target: Object | Function,
    key: string,
    descriptor: PropertyDescriptor
): PropertyDescriptor | void {
    var returnType = Reflect.getMetadata("design:returntype", target, key);

    console.log(returnType);
}

이 메서드 데코레이터를 원하는 메서드에 스냅하면 메서드 호출에서 반환 된 것으로 추정되는 개체의 생성자 함수에 대한 정확한 참조가 있습니다.

class TestClass {
    @logReturnType // logs Number (a string representation)
    public test(): number {
        return 42;
    }
}

그러나이 접근 방식에는 몇 가지 주목할만한 제한 사항이 있습니다.

  • 이렇게 데코 레이팅 된 메서드에서 반환 유형을 명시 적으로 정의해야합니다. 그렇지 않으면에서 정의되지 않습니다 Reflect.getMetadata.
  • 컴파일 후에도 존재하는 실제 유형 만 참조 할 수 있습니다. 즉, 인터페이스 또는 제네릭 없음

또한 데코레이터와 리플렉션 메타 데이터 모두이 게시물을 작성하는 현재 실험적인 기능이므로 typescript 컴파일러에 대해 다음 명령 줄 인수를 지정해야합니다.

--emitDecoratorMetadata --experimentalDecorators

0

나는 잘 작동하는 것처럼 보이는 다음을 생각해 냈습니다.

function returnType<A, B, Z>(fn: (a: A, b: B) => Z): Z
function returnType<A, Z>(fn: (a: A) => Z): Z
function returnType<Z>(fn: () => Z): Z
function returnType(): any {
    throw "Nooooo"
}

function complicated(value: number): { kind: 'complicated', value: number } {
    return { kind: 'complicated', value: value }
}

const dummy = (false as true) && returnType(complicated)
type Z = typeof dummy

1
어쨌든 함수 인수를 버리고 있기 때문에 함수 인수가 일반적 일 필요는 없다고 생각합니다. fn: (...args: any[]) => Z필요한 것은 전부입니다.
Aaron Beall
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.