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

时间:2018-09-05 11:26:35

标签: reactjs typescript redux typescript-typings redux-thunk

亲爱的TypeScript-3-Gurus,

有人可以帮助我定义执行以下操作的泛型类型GuruMagic<T>吗?

T是一个返回函数的函数,例如这个:

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

然后,泛型类型应使用返回的函数的ReturnType 替换 fetchUser中的ReturnType。像这样:

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

我知道我可以两次申请ReturnType来获得Promise<boolean>,但是我不知道如何用这种返回类型连接原始参数(可能是多个)。使用TypeScript(3.x)甚至可能吗?

为清楚起见,其他示例

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

动机

Typesafe Redux-Thunk。当我connect一个react组件时,如果我能做到这一点,那就太好了:

import { fetchUser } from './myActions';

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

// ... MyComponent Definition ...

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

1 个答案:

答案 0 :(得分:2)

是的,您可以使用conditional types并通过对tuple types in rest and spread expressions的支持在TypeScript 3.0中引入通用的参数列表操作功能。这是一种实现方法:

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

因此,您将函数FF的参数列表推断为A,并将函数FF的返回类型的返回类型推断为R,然后返回从AR的参数列表的新函数。可以吗?

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

是的!

我不确定100%会在实践中使用此类型函数...它忽略了中间函数的参数类型这一事实让我感到担忧。给定类型为GuruMagic<T>的函数,如果您尝试实际实现类型为T的函数,除非您以某种方式提供缺少的参数,否则您将遇到问题。但是也许您甚至都没有实现给定GuruMagic<T>的{​​{1}}。无论如何,那是你的事,而不是我的事。

无论如何,希望能有所帮助。祝你好运!