Общий TypeScript Type для функций, возвращающих функции, которые заменяют ReturnType на ReturnType возвращаемой функции - PullRequest
0 голосов
/ 05 сентября 2018

Уважаемый TypeScript-3-Гуру,

Может ли кто-нибудь помочь мне определить универсальный тип 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 a react компонент, было бы здорово, если бы я мог просто сделать это:

import { fetchUser } from './myActions';

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

// ... MyComponent Definition ...

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

1 Ответ

0 голосов
/ 05 сентября 2018

Да, вы можете сделать это с условными типами и общими возможностями манипулирования списком аргументов, представленными в 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, а затем возвращаете новую функцию из списка аргументов A до R. Это работает?

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> с T. Во всяком случае, это ваше дело, а не мое.

В любом случае, надеюсь, это поможет. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...