获取函数的返回类型

时间:2016-03-15 15:34:22

标签: typescript typescript1.8

我有以下功能:

function test(): number {
    return 42;
}

我可以使用typeof

获取函数的类型
type t = typeof test;

此处,t将为() => number

有没有办法获得函数的返回类型?我希望tnumber而不是() => number

8 个答案:

答案 0 :(得分:76)

修改

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

有关详细信息,请参阅here

TypeScript太棒了!

老派黑客

不幸的是,Ryan的回答再也不起作用了。但是我用黑客修改了它,我对此感到非常高兴。看哪:

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

它通过将false转换为true的文字值来工作,因此类型系统认为返回值是函数的类型,但是当您实际运行代码时,它会在false时短路。

TypeScript是最好的。 :d

答案 1 :(得分:14)

TypeScript 2.8中最简单的方法:

fs.realpath()

答案 2 :(得分:4)

没有办法执行此操作(有关添加此项的工作项跟踪,请参阅https://github.com/Microsoft/TypeScript/issues/6606。)

常见的解决方法是编写如下内容:

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

答案 3 :(得分:3)

以下代码无需执行该功能即可运行。它来自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 :(得分:2)

编辑: 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函数,但它调用原始函数。您可以阻止使用getReturnType进行(false as true) && getReturnType(foo)来电,但IMO这会让它更加混乱。

我刚刚使用这个方法和一些regexp find / replace来迁移一个旧的Angular 1.x项目,该项目有大约1500个这样的工厂函数,最初是在JS中,并且将Foo等类型添加到所有用途......令人惊讶的是,你会发现破碎的代码。 :)

答案 5 :(得分:1)

如果有问题的函数是用户定义类的方法,则可以使用method decoratorsReflect Metadata结合使用来确定运行时的返回类型(构造函数) >(和它一起,按你认为合适的方式行事)。

例如,您可以将其记录到控制台:

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

答案 6 :(得分:0)

如果不遗憾地执行它,就无法检索函数的返回类型。 这是因为当TypeScript被编译成JS时,您将丢失有关类型的所有信息。

答案 7 :(得分: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