Как правильно использовать функцию extends с параметрами и ReturnType - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь создать собственную функцию запоминания для повторного выбора. Мне пришлось переопределить Parameters и ReturnType, чтобы принять extends Function (ошибка?). Подпись для myMemoize правильная, однако подпись внутренней функции не компилируется.

import { createSelectorCreator } from "reselect";

type Parameters<T extends Function> = T extends (...args: infer P) => any ? P : never;
type ReturnType<T extends Function> = T extends (...args: any[]) => infer R ? R : any;

function myMemoize<F extends Function>(func: F): F {
  // ...
  return function(...args: Parameters<F>): ReturnType<F> {
    //...
    return func.apply(null, args)
  }
}

export const createMyMemoizeSelector = createSelectorCreator(myMemoize)

Ошибка:

error TS2322: Type '(...args: Parameters<F>) => ReturnType<F>' is not assignable to type 'F'

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Проблема в том, что ваша новая функция на самом деле не того же типа, что и оригинал. У оригинала могут быть дополнительные свойства, которые вы не отправляете в функцию возврата.

Вы можете просто пропустить возвращаемый тип, а также Parameters и ReturnType (оба из которых определены, поэтому не переопределяйте их), на самом деле не требуется для полной типизированной версии:

function myMemoize<P extends any[], R>(func: (...a:P)=> R): (...a:P)=> R {
  // ...
  return function(...args: P): R {
    //...
    return func.apply(null, args)
  }
}

Не уверен, как это взаимодействует с createSelectorCreator.

0 голосов
/ 21 марта 2019

Type '(...args: Parameters<F>) => ReturnType<F>' is not assignable to type 'F'

Фундаментально ...args подразумевает любое количество аргументов, тогда как F может принимать очень специфическое число.

Fix

Вам не нужен Prameters / ReturnType для вашего случая использования, поскольку (func: F): F охватывает безопасность внешнего типа, и вам не нужна безопасность внутреннего типа. Вот более простой способ:

function myMemoize<F extends Function>(func: F): F {
  // ...
  return function(...args: any[]): any {
    //...
    return func.apply(null, args)
  }
}
...