获取函数的返回类型
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<typeof fn>
(答案暗示ReturnType<fn>
就足够了)。
我怎样才能取消看到这个?
是否有类似的方法来获取函数的参数?【参考方案2】:
TypeScript 2.8 中最简单的方法:
const foo = (): FooReturnType =>
type returnType = ReturnType<typeof foo>;
// returnType = FooReturnType
【讨论】:
【参考方案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
函数,但它不调用原始函数。您可以使用(false as true) && getReturnType(foo)
阻止getReturnType
调用,但IMO 只会让它更加混乱。
我只是使用这个方法和一些正则表达式查找/替换来迁移一个旧的 Angular 1.x 项目,该项目有大约 1500 个这样编写的工厂函数,最初是在 JS 中,并将 Foo
等类型添加到所有用途中。 . 令人惊奇的破代码会发现。 :)
【讨论】:
谢谢!虽然很遗憾,它需要这么多的措辞,但它至少有效! @ecmanaut 我们不再需要这个了!在 TS 2.8 中,您可以使用ReturnType<F>
获取函数返回类型。 :)
这里的答案与问题的示例基础大相径庭,因此很难弄清楚如何生成函数 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[]) => 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/…以上是关于获取函数的返回类型的主要内容,如果未能解决你的问题,请参考以下文章