获取函数的返回类型

Posted

技术标签:

【中文标题】获取函数的返回类型【英文标题】:Obtaining the return type of a function 【发布时间】:2016-07-01 03:40:32 【问题描述】:

我有以下功能:

function test(): number 
    return 42;

我可以通过typeof获取函数的类型:

type t = typeof test;

这里,t 将是 () => number

有没有办法?我希望 t 成为 number 而不是 () => number

【问题讨论】:

不,无论如何都不是 typeof。 typeof 只会返回“function”(我的大小写可能是错误的)。 如果这成为可能,那就太好了。有时,您在将类型推出函数时定义类型,并且没有(好的)方法来捕获这种结构。 【参考方案1】:

编辑

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

详情请见this pull request to Microsoft/TypeScript。

TypeScript 太棒了!


老派黑客

不幸的是,Ryan 的回答不再有效。但是我用一个我非常高兴的黑客修改了它。看:

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

它通过将false 转换为true 的字面值来工作,这样类型系统就会认为返回值是函数的类型,但是当你实际运行代码时,它会在false 上短路.

【讨论】:

for flow: const DUMMY = ((null: any): Object) && fn() export type Type = typeof DUMMY @NSjonas 你需要告诉 vscode 使用其他版本。我想他在右下角的状态栏上。 我不得不做ReturnType&lt;typeof fn&gt;(答案暗示ReturnType&lt;fn&gt;就足够了)。 我怎样才能取消看到这个? 是否有类似的方法来获取函数的参数?【参考方案2】:

TypeScript 2.8 中最简单的方法:

const foo = (): FooReturnType => 


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

【讨论】:

【参考方案3】:

编辑: TS 2.8 不再需要此功能! ReturnType&lt;F&gt; 给出返回类型。查看已接受的答案。


我正在使用的一些先前答案的变体,它适用于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函数,但它调用原始函数。您可以使用(false as true) &amp;&amp; getReturnType(foo) 阻止getReturnType 调用,但IMO 只会让它更加混乱。

我只是使用这个方法和一些正则表达式查找/替换来迁移一个旧的 Angular 1.x 项目,该项目有大约 1500 个这样编写的工厂函数,最初是在 JS 中,并将 Foo 等类型添加到所有用途中。 . 令人惊奇的破代码会发现。 :)

【讨论】:

谢谢!虽然很遗憾,它需要这么多的措辞,但它至少有效! @ecmanaut 我们不再需要这个了!在 TS 2.8 中,您可以使用 ReturnType&lt;F&gt; 获取函数返回类型。 :) 这里的答案与问题的示例基础大相径庭,因此很难弄清楚如何生成函数 test 的返回类型。这个答案是仅将test 重命名为foo 的更有用的答案之一(并且诚然会产生更复杂的返回类型,用于踢球)。如果您已经知道如何将它们应用于原始示例,那么接受的答案和您的评论可能都很棒。 (现在是深夜,我并没有立即看出完整的 ReturnType 示例的语法是什么样的。)【参考方案4】:

下面的代码在不执行函数的情况下工作。它来自 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;

【讨论】:

【参考方案5】:

我想出了以下方法,似乎效果很好:

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

【讨论】:

我认为函数 args 不需要是通用的,因为无论如何你都要把它们扔掉。 fn: (...args: any[]) =&gt; Z 就是你所需要的。【参考方案6】:

如果所讨论的函数是用户定义类的方法,您可以结合使用method decorators 和Reflect 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

【讨论】:

【参考方案7】:

没有办法做到这一点(请参阅https://github.com/Microsoft/TypeScript/issues/6606 了解添加此的工作项跟踪)。

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

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

【讨论】:

我认为这种变通办法不再有效 - 可能是因为基于控制流的类型分析。 @JKillian 你是对的,建议的例子不再有效,虽然你可以很容易地用!1而不是false欺骗TypeScript——typescriptlang.org/play/…

以上是关于获取函数的返回类型的主要内容,如果未能解决你的问题,请参考以下文章

在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型

如何从返回向量的函数中获取向量值?

使用 JDBC 从存储过程中获取 Oracle 表类型

表值函数返回类型

函数 ajax 返回值的问题

Flask04 后台获取请求数据视图函数返回类型前台接受响应数据