【问题标题】:how to call an overloaded function with the spread operator如何使用扩展运算符调用重载函数
【发布时间】:2021-01-01 18:19:29
【问题描述】:

我想使用扩展运算符从 fp-ts 调用 pipe function,但它没有为此过载。

相反,我不得不将 pipe 强制转换为 any,这看起来很难看,并且会损害可读性。

我可以扩充现有类型吗?

我创建了这个简单的例子,这里是codesandbox。现实世界的例子让我无法确切知道我将传递多少个参数给管​​道。

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

【问题讨论】:

    标签: typescript fp-ts


    【解决方案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 有两个功能。 concatempty concat 是获取两个值并将其连接在一起的函数,而 empty 是当您的类型没有任何值时它将获得空值。

    例如 sum 的 monoid 是这样的

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

    您可以在数组的foldMap 上使用此monoidSum 并获取整数列表的总和。

    这里我们使用了一个名为getEndomorphismMonoid 的函数,这是一个内置在fp-ts 中的函数。 Endmorphism 是指接受一个参数作为输入并返回相同类型的函数。

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

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

    【讨论】:

    • 先生,谢谢。这为我学习开辟了新事物
    【解决方案2】:

    您可以尝试以下方法吗?

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

    【讨论】:

    • 抱歉,我给出的例子并不能很好地反映现实世界的例子。我现在已经将问题和代码框更新为相当准确的内容。
    • 也许你可以先定义固定长度的元组type TupleOf&lt;T, N extends number&gt; = N extends N ? number extends N ? T[] : _TupleOf&lt;T, N, []&gt; : never; type _TupleOf&lt;T, N extends number, R extends unknown[]&gt; = R['length'] extends N ? R : _TupleOf&lt;T, N, [T, ...R]&gt;; 并转换它return pipe(o, ...(getters as TupleOf&lt;G, 19&gt;)) `
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多