Расширение массива fns при составлении приводит к «Ожидаемым 1-6 аргументам, но получено 0 или более»

#typescript #ramda.js

#typescript #ramda.js

Вопрос:

Я понимаю, что typescript видит распространение и предполагает, что оно может быть любой длины, и именно поэтому жалуется на слишком много аргументов (арность функции compose равна 1-6).

Как я могу удовлетворить компилятор при получении массива функций неизвестной длины?

 import { compose } from "ramda";


//As long as the compiles is concerned fns might be any length (even more than 6)
const fns = [
    n => n * 10,
    n => n   1,
  ]

const composed = compose(...fns) //Typescript: "Expected 1 - 6 arguments, but got 0 or more"
 

Ответ №1:

Если вы хотите, чтобы компилятор знал, сколько элементов имеет литерал массива, вы можете использовать const утверждение, чтобы попросить компилятор вывести его как кортеж:

 const fns = [
  (n: number) => n * 10,
  (n: number) => n   1,
] as const;

/* const fns: readonly [(n: number) => number, (n: number) => number] */
 

(Также обратите внимание, что я аннотирую аргументы обратного вызова как number , поскольку в противном случае вы получите неявное any значение, которое вам, вероятно, не нужно).

Затем compose() будет работать, как ожидалось:

 const composed = compose(...fns); // no error
 

Ссылка на игровую площадку для кода

Ответ №2:

Я нашел обходной путь из этого потока:

 const composeList = list => R.reduceRight(R.compose,R.identity, list)

const composed = composeList(fns) //No longer upsets the compiler
composed(2) //=> 30
 

Насколько я понимаю приведенный выше фрагмент, мы передаем каждый элемент в list compose функцию один за другим. В этом случае R.identity в середине будет возвращена последняя функция (либо fn[0] в массиве, либо a compose(fn) , где fn — составленная версия последнего fn.

Это было бы эквивалентно R.compose(R.compose(fns[0]),fns[1]) тому, где он вкладывает композицию для каждого элемента в массиве. Поскольку я вызываю каждый compose из них с 1-2 аргументами, это больше не расстраивает компилятор.

Комментарии:

1. Теперь вы просто ограничены размером вашего стека. Список не может быть длиннее, чем количество фреймов стека, которое допускает ваш интерпретатор JS.