Programing

함수의 반환 유형 얻기

crosscheck 2020. 12. 4. 07:53
반응형

함수의 반환 유형 얻기


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

function test(): number {
    return 42;
}

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

type t = typeof test;

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

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


편집하다

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[]

자세한 내용은 여기참조 하십시오 .

TypeScript는 굉장합니다!


구식 해킹

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

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

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

TypeScript가 최고입니다. :디


TypeScript 2.8에서 가장 쉬운 방법 :

const foo = (): FooReturnType => {
}

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

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

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

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

아래 코드는 함수를 실행하지 않고 작동합니다. 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;

편집 : 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; }

It does call the getReturnType function, but it does not call the original function. You could prevent the getReturnType call using (false as true) && getReturnType(foo) but IMO this just makes it more confusing.

I just used this method with some regexp find/replace to migrate an old Angular 1.x project that had ~1500 factory functions written like this, originally in JS, and added the Foo etc types to all uses... amazing the broken code one will find. :)


If the function in question is a method of a user defined class, you can use method decorators in conjuction with Reflect Metadata to determine the return type (constructor function) at runtime (and with it, do as you see fit).

For example, you could log it to the console:

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

    console.log(returnType);
}

Just snap this method decorator on a method of your choice and you have the exact reference to the constructor function of the object that is supposedly returned from the method call.

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

There are a few notable limitations to this approach, however:

  • you need to explicitly define the return type on a method decorated as such, otherwise you'll get undefined from Reflect.getMetadata,
  • you can only reference actual types which also exist after compilation; that is, no interfaces or generics

Also, you'll need to specify the following command line arguments for the typescript compiler, because both decorators and reflect metadata are experimental features as of writing this post:

--emitDecoratorMetadata --experimentalDecorators

There's no way of retrieving the return type of the function without executing it sadly. This is because when TypeScript gets compiled into JS, you lose all information regarding type.


I came up with the following, which seems to work nicely:

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

참고URL : https://stackoverflow.com/questions/36015691/obtaining-the-return-type-of-a-function

반응형