Вывод функционального типа Typescript - PullRequest
0 голосов
/ 07 ноября 2018

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

const compose = <T, R>(...fns: Array<(a: any) => any>) => (a: T): R =>
  fns.reduce((b, f) => f(b), a);

const greet = (s: string) => "Hello " + s;
const toUpperCase = (s: string) => s.toUpperCase();
const log = console.log;

const upperCaseAndLog = compose<string, void>(
  greet,
  toUpperCase,
  log
);

upperCaseAndLog("bill");

Я что-то упустил, есть ли более элегантный способ достижения той же цели? Я предполагаю, что такие языки, как F # или Haskell, смогут выводить типы без какой-либо дополнительной информации.

1 Ответ

0 голосов
/ 07 ноября 2018

Typescript не может вывести такие связанные типы (связанные в том смысле, что аргумент функции зависит от результата предыдущей функции).

Вы даже не можете определить сигнатуру compose достаточно широко, чтобы она работала для ряда функций. Что мы можем сделать, это определить перегрузки, которые принимают до заданного числа функций:

type Fn<A, R> = (a: A) => R // just to be a bit shorter in the compose signature, you can use teh function signature directly  
function compose<T, P1, P2, R>(fn1: Fn<T, P1>, fn2: Fn<P1, P2>, f3: Fn<P2, R>) : Fn<T, R>
function compose<T, P1, R>(fn1: Fn<T, P1>, f2: Fn<P1, R>) : Fn<T, R>
function compose(...fns: Array<(a: any) => any>) {
    return function (a: any) {
        return fns.reduce((b, f) => f(b), a);
    }
}

const greet = (s: string) => "Hello " + s;
const toUpperCase = (s: string) => s.toUpperCase();
const log = console.log;

const upperCaseAndLog = compose(
    greet,
    toUpperCase,
    log
);

upperCaseAndLog("bill");//(a: string) => void
...