Я хочу вызвать функцию pipe из fp-ts с помощью оператора spread, но у него нет перегрузки для этого.

Вместо этого мне приходится приводить pipe к any, что выглядит некрасиво и ухудшает читабельность.

Можно ли расширить существующий тип?

Я создал этот простой пример и вот codesandbox. Реальный пример не позволяет мне точно знать, сколько аргументов я буду передавать в pipe.

import { pipe } from "fp-ts/function";

const o = { a: "a", b: "b", c: "c" };

type O = typeof o;
type G = (o: O) => O;

const set = (...getters: G[]) => {
  /*
  Ожидалось 1-20 аргументов, но получено 0 или больше.ts(2556)
  function.d.ts(225, 33): Аргумент 'a' не был
  */
  return pipe(...getters);
  // это работает, но некрасиво
  // return (pipe as any)(...getters);
};

const getters: G[] = [
  (o: O) => ({ ...o, a: "5" }),
  (o: O) => ({ ...o, b: "6" }),
  (o: O) => ({ ...o, c: "8" })
];

set(...getters);

dagda1

Ответов: 2

Ответы (2)

Я думаю, что это работа для моноида.


import { foldMap } from "fp-ts/Array";
import { getEndomorphismMonoid } from "fp-ts/lib/Monoid";
import { identity, pipe } from "fp-ts/lib/function";

const o = { a: "a", b: "b", c: "c" };

type O = typeof o;
type G = (o: O) => O;

const monoid = getEndomorphismMonoid();

const set = (getters: G[]) => pipe(getters, foldMap(monoid)(identity));

const getters: G[] = [
  (o: O) => ({ ...o, a: "5" }),
  (o: O) => ({ ...o, b: "6" }),
  (o: O) => ({ ...o, c: "8" }),
];

console.log(set(getters)(o));


Я не знаю, знакомы ли вы с моноидом или нет, но моноид - это типовой класс с двумя функциями. concat и empty, concat - это функция, которая получает два значения и объединяет их вместе, а empty - это когда у типа нет никакого значения, он получит пустое значение.

например, моноид для суммы выглядит следующим образом

const monoidSum: monoid = {
  concat: (x, y) => x + y,
  пусто: 0
}

Вы можете использовать эту monoidSum на foldMap массива и получить сумму списка целых чисел.

Здесь мы используем функцию getEndomorphismMonoid это функция, которая встроена в fp-ts. Эндоморфизм означает функцию, которая принимает один аргумент на вход и возвращает тот же тип.

export interface Endomorphism {
  (a: A): A
}

для concat он соединит две функции вместе, а для empty он использует функцию identity.

Вы можете попробовать следующее?

const getters = [
  (o: O) => ({ ...o, a: "5" }),
  (o: O) => ({ ...o, b: "6" }),
  (o: O) => ({ ...o, c: "8" })
] as const;

const lotsOfO = pipe(o, ...getters);

getters должен быть постоянным, чтобы typescript вывел правильную форму перегрузки, то есть количество параметров в данном случае.

2022 WebDevInsider