获取函数的 return 类型
Obtaining the return type of a function
我有以下功能:
function test(): number {
return 42;
}
我可以通过typeof
:
获取函数的类型
type t = typeof test;
在这里,t
将是 () => number
。
有没有办法获取函数的return类型?我希望 t
成为 number
而不是 () => number
。
没有办法做到这一点(请参阅 https://github.com/Microsoft/TypeScript/issues/6606 了解添加此功能的工作项跟踪)。
一个常见的解决方法是这样写:
var dummy = false && test();
type t2 = typeof dummy;
如果有问题的函数是用户定义的方法 class,您可以使用 method decorators in conjuction with Reflect Metadata 来确定 return 类型(构造函数)在 runtime(并随心所欲地做)。
例如,您可以将其记录到控制台:
function logReturnType(
target: Object | Function,
key: string,
descriptor: PropertyDescriptor
): PropertyDescriptor | void {
var returnType = Reflect.getMetadata("design:returntype", target, key);
console.log(returnType);
}
只需将此方法装饰器捕捉到您选择的方法上,您就可以准确引用对象的构造函数,据推测,该对象是从方法调用中 return 编辑的。
class TestClass {
@logReturnType // logs Number (a string representation)
public test(): number {
return 42;
}
}
但是,这种方法有一些明显的局限性:
- 您需要在这样装饰的方法上显式定义 return 类型,否则您会从
Reflect.getMetadata
、 中得到未定义
- 您只能引用编译后也存在的实际类型;也就是说,没有接口或泛型
此外,您还需要为打字稿编译器指定以下命令行参数,因为装饰器和反射元数据在撰写本文时都是实验性功能 post:
--emitDecoratorMetadata --experimentalDecorators
编辑
从 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 的回答不再有效。但是我用一个让我非常高兴的 hack 修改了它。看:
const fnReturnType = (false as true) && fn();
它的工作原理是将 false
转换为 true
的字面值,这样类型系统就认为 return 值是函数的类型,但是当你实际上 运行 代码,它在 false
.
上短路
我想出了以下方法,似乎效果很好:
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
下面的代码在不执行函数的情况下工作。它来自 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>
给出 return 类型。查看已接受的答案。
我正在使用的一些先前答案的变体,它在 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
调用,但在我看来,这只会让事情变得更加混乱。
我只是用这个方法和一些正则表达式 find/replace 来迁移一个旧的 Angular 1.x 项目,它有大约 1500 个这样写的工厂函数,最初是在 JS 中,并添加了Foo
等类型的所有用途...人们会发现破损的代码令人惊奇。 :)
TypeScript 2.8 中最简单的方法:
const foo = (): FooReturnType => {
}
type returnType = ReturnType<typeof foo>;
// returnType = FooReturnType
使用built-inReturnType
:
type SomeType = ReturnType<typeof SomeFunc>
ReturnType
扩展为:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
我有以下功能:
function test(): number {
return 42;
}
我可以通过typeof
:
type t = typeof test;
在这里,t
将是 () => number
。
有没有办法获取函数的return类型?我希望 t
成为 number
而不是 () => number
。
没有办法做到这一点(请参阅 https://github.com/Microsoft/TypeScript/issues/6606 了解添加此功能的工作项跟踪)。
一个常见的解决方法是这样写:
var dummy = false && test();
type t2 = typeof dummy;
如果有问题的函数是用户定义的方法 class,您可以使用 method decorators in conjuction with Reflect Metadata 来确定 return 类型(构造函数)在 runtime(并随心所欲地做)。
例如,您可以将其记录到控制台:
function logReturnType(
target: Object | Function,
key: string,
descriptor: PropertyDescriptor
): PropertyDescriptor | void {
var returnType = Reflect.getMetadata("design:returntype", target, key);
console.log(returnType);
}
只需将此方法装饰器捕捉到您选择的方法上,您就可以准确引用对象的构造函数,据推测,该对象是从方法调用中 return 编辑的。
class TestClass {
@logReturnType // logs Number (a string representation)
public test(): number {
return 42;
}
}
但是,这种方法有一些明显的局限性:
- 您需要在这样装饰的方法上显式定义 return 类型,否则您会从
Reflect.getMetadata
、 中得到未定义
- 您只能引用编译后也存在的实际类型;也就是说,没有接口或泛型
此外,您还需要为打字稿编译器指定以下命令行参数,因为装饰器和反射元数据在撰写本文时都是实验性功能 post:
--emitDecoratorMetadata --experimentalDecorators
编辑
从 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 的回答不再有效。但是我用一个让我非常高兴的 hack 修改了它。看:
const fnReturnType = (false as true) && fn();
它的工作原理是将 false
转换为 true
的字面值,这样类型系统就认为 return 值是函数的类型,但是当你实际上 运行 代码,它在 false
.
我想出了以下方法,似乎效果很好:
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
下面的代码在不执行函数的情况下工作。它来自 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>
给出 return 类型。查看已接受的答案。
我正在使用的一些先前答案的变体,它在 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
调用,但在我看来,这只会让事情变得更加混乱。
我只是用这个方法和一些正则表达式 find/replace 来迁移一个旧的 Angular 1.x 项目,它有大约 1500 个这样写的工厂函数,最初是在 JS 中,并添加了Foo
等类型的所有用途...人们会发现破损的代码令人惊奇。 :)
TypeScript 2.8 中最简单的方法:
const foo = (): FooReturnType => {
}
type returnType = ReturnType<typeof foo>;
// returnType = FooReturnType
使用built-inReturnType
:
type SomeType = ReturnType<typeof SomeFunc>
ReturnType
扩展为:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;