1

我想使用扩展运算符从 fp-ts 调用管道函数,但它没有重载。

相反,我不得不强制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[]) => {
  /*
  Expected 1-20 arguments, but got 0 or more.ts(2556)
  function.d.ts(225, 33): An argument for 'a' was not
  */
  return pipe(...getters);
  // this works but is ugly
  // 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);
4

2 回答 2

1

我认为这是幺半群的工作。


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<O>();

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));


我不知道你是否熟悉 Monoid,但是一个 monoid 是 typeclass 有两个功能。 concat并且emptyconcat 是获取两个值并将其连接在一起的函数,而 empty 是当您的类型没有任何值时,它将获得空值。

例如 sum 的 monoid 是这样的

const monoidSum: Monoid<number> = {
  concat: (x, y) => x + y,
  empty: 0
}

您可以monoidSumfoldMap数组中使用它并获取整数列表的总和。

这里我们使用一个函数叫做getEndomorphismMonoidthis 是一个内置在里面的函数fp-ts。Endmorphism 是指接受一个参数作为输入并返回相同类型的函数。

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

对于 concat ,它将两个函数连接在一起,对于空的,它使用该identity函数。

于 2021-01-04T18:42:31.977 回答
0

你可以试试以下吗?

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必须保持不变,以便打字稿推断出正确的重载形式,即在这种情况下的参数数量。

于 2021-01-01T18:41:10.617 回答