简体   繁体   English

函数返回函数的通用TypeScript类型,该函数将ReturnType替换为返回函数的ReturnType

[英]Generic TypeScript Type for functions returning functions that replaces the ReturnType with the ReturnType of the returned function

Dear TypeScript-3-Gurus out there, 亲爱的TypeScript-3-Gurus,

can someone help my define a generic type GuruMagic<T> that does the following? 有人可以帮助我定义以下类型的通用类型GuruMagic<T>吗?

T is a function returning a function, eg this: T是一个返回函数的函数,例如:

fetchUser(id: Id) => (dispatch: Dispatch) => Promise<boolean>

The generic type should then replace the ReturnType of fetchUser with the ReturnType of the returned function. 然后,泛型类型应将ReturnTypefetchUser 替换为返回函数的ReturnType Like this: 像这样:

type dispatchedAction = GuruMagic<typeof fetchUser>;
// so that dispatchedAction === (id: Id) => Promise<boolean>

I know that I can apply ReturnType two times to get Promise<boolean> , but I don't know how to concat the original parameters (possibly multiple) with this return type. 我知道我可以两次应用ReturnType来获取Promise<boolean> ,但是我不知道如何用这种返回类型连接原始参数(可能是多个)。 Is this even possible with TypeScript (3.x)? 使用TypeScript(3.x)甚至可能吗?

Other examples for clarity 为清楚起见,其他示例

const f1 = (a: number, b: string) => () => a;
type guruF1 = GuruMagic<typeof f1>; // (a: number, b: string) => number

const f2 = () => (name: string) => (otherName: string) => name + otherName;
type guruF2 = GuruMagic<typeof f2>; // () => (otherName: string) => string

Motivation 动机

Typesafe Redux-Thunk . Typesafe Redux-Thunk When I connect a react component it would be great if I could just do this: 当我connect一个react组件时,如果我能做到这一点就太好了:

import { fetchUser } from './myActions';

interface IPropsOfMyComponent {
  fetchUser: GuruMagic<typeof fetchUser>;
}

// ... MyComponent Definition ...

connect<{}, IPropsOfMyComponent, {}>(null, { fetchUser })(MyComponent)

Yes, you can do this with conditional types and the generic argument-list manipulation powers introduced in TypeScript 3.0 via support for tuple types in rest and spread expressions . 是的,您可以使用条件类型和TypeScript 3.0中引入的通用参数列表操作能力来实现这一点,方法是支持rest和spread表达式中的元组类型 Here's one way to do it: 这是一种实现方法:

type GuruMagic<FF extends (...args: any[]) => (...args: any[]) => any> =
  FF extends (...args: infer A) => (...args: infer _) => infer R ? (...args: A) => R 
  : never;

So you infer the argument list for the function FF as A , and the return type of the return type of the function FF as R , and then return a new function from an argument list of A to R . 所以,你推断该函数的参数列表FFA ,和函数的返回类型的返回类型FFR然后从参数列表返回一个新的功能, AR Does it work? 它行得通吗?

declare function fetchUser(id: Id): (dispatch: Dispatch) => Promise<boolean>
type dispatchedAction = GuruMagic<typeof fetchUser>;
// (id: Id) => Promise<boolean>

const f1 = (a: number, b: string) => () => a;
type guruF1 = GuruMagic<typeof f1>; 
// (a: number, b: string) => number

const f2 = () => (name: string) => (otherName: string) => name + otherName;
type guruF2 = GuruMagic<typeof f2>; 
// () => (otherName: string) => string

Yes it does! 是的,它确实!

I'm not 100% sure how you will use this type function in practice... the fact that it ignores the type of the arguments of the intermediate function worries me. 我不是100%地确定您将如何在实践中使用此类型函数……事实上,它忽略了中间函数的参数类型,这一点令我感到担忧。 If you try to actually implement a function of type GuruMagic<T> given a function of type T you will have a problem unless you supply the missing arguments somehow. 如果尝试给定类型T的函数实际实现类型为GuruMagic<T>的函数,除非您以某种方式提供缺少的参数,否则您将遇到问题。 But maybe you're not even implementing a GuruMagic<T> given a T . 但是也许您甚至没有实现给定TGuruMagic<T> Anyway, that's your business, not mine. 无论如何,这是您的事,而不是我的事。

Anyway, hope that helps. 无论如何,希望能有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM