#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.