TypeScript: тип 'T' не удовлетворяет ограничению '(... args: any) => any' - PullRequest
2 голосов
/ 27 марта 2020

У меня есть следующий создатель избыточного действия:

function updateInitiator(form_request_id, { to_recipient }) {
  return (dispatch) => {
    const url = `/some/url`;
    const data = { to_recipient };

    return fetch(url, { method: 'PUT', body: JSON.stringify(data) }).then(() => {
      dispatch(fetchResponses());
    });
  };
}

Затем я объявляю тип функции:

type UpdateInitiator = typeof updateInitiator;

Я пытаюсь получить тип связанное действие. Короче говоря, когда создатель действия «связан» в реакции-избыточности, он автоматически вызывает функцию, возвращаемую с dispatch, а затем возвращает результат возврата этой внутренней функции. Я пытаюсь объявить тип для этого поведения. Это работает, если я делаю это без обобщений:

type BoundUpdateInitiator = (...args: Parameters<UpdateInitiator>) => ReturnType<ReturnType<UpdateInitiator>>;

Но когда я пытаюсь объявить обобщенный тип c для любой связанной функции, у меня возникают некоторые проблемы:

type BoundThunk<T> = (...args: Parameters<T>) => ReturnType<ReturnType<T>>;
type BoundUpdateInitiator = BoundThunk<UpdateInitiator>;

Это дает мне ошибку:

error TS2344: Type 'T' does not satisfy the constraint '(...args: any) => any'.

236 type BoundThunk<T> = (...args: Parameters<T>) => ReturnType<ReturnType<T>>;
                                              ~

error TS2344: Type 'ReturnType<T>' does not satisfy the constraint '(...args: any) => any'.
  Type 'unknown' is not assignable to type '(...args: any) => any'.
    Type '{}' provides no match for the signature '(...args: any): any'.

236 type BoundThunk<T> = (...args: Parameters<T>) => ReturnType<ReturnType<T>>;
                                                                ~~~~~~~~~~~~~

error TS2344: Type 'T' does not satisfy the constraint '(...args: any) => any'.

236 type BoundThunk<T> = (...args: Parameters<T>) => ReturnType<ReturnType<T>>;
                                                                           ~

Я смутно понимаю, что T может быть чем-то отличным от функции, и аналогично ReturnType<T> также может не быть функцией, и это обобщенно c тип может не учитывать эти случаи. Однако у меня возникают проблемы с пониманием того, как я могу объяснить их. В идеале, не позволяя им. Есть предложения?

1 Ответ

3 голосов
/ 27 марта 2020

Чтобы выполнить sh, мы бы использовали обобщенное ограничение типа c.

На самом деле это то, как параметры типа языка предоставляют вспомогательные типы Parameters<T> и ReturnType<T >. и что в свою очередь вызывает ошибку.

Чтобы создать экземпляр обобщенного типа c, скажем ReturnType<T>, с нашим параметром типа, наш параметр типа должен быть ограничен по крайней мере так же ограничительно, как параметр типа ReturnType. Глядя на определение ReturnType<T>, мы можем определить минимальные ограничения, которые нам нужно применить, и связанный с ними синтаксис

type ReturnType<T extends (...args: any) => any> =
    // details

Не беспокойтесь о реализации (после =), поскольку это более широкий топи c. В этой ситуации мы сосредоточимся на ограничениях T, определенных с использованием ключевого слова extends при объявлении T.

Следовательно, чтобы передать T declared на BoundThunk<T> в ReturnType<T> мы должны ограничить его, чтобы он отвечал вышеуказанным требованиям (обратите внимание, что Parameters<T> имеет идентичные ограничения).

type BoundThunk<T extends (...args: any) => any> =
    (...args: Parameters<T>) => ReturnType<ReturnType<T>>;

Однако наши требования к T на самом деле больше ограничительны, поскольку мы применяем ReturnType дважды, ReturnType<ReturnType<T>>, подразумевая, что T является функцией более высокого порядка, в этом случае функция, которая возвращает функцию.

Поэтому мы уточним наше ограничение соответственно

type BoundThunk<T extends (...args: any) => (...args: any) => any> =
    (...args: Parameters<T>) => ReturnType<ReturnType<T>>;
...