【问题标题】:How should the lodash flow function be typed in typescript?lodash流函数应该如何在打字稿中输入?
【发布时间】:2016-05-16 21:46:07
【问题描述】:

lodash.flow 结合了两个或多个功能。

lodash.flow(double, addTwo) 将返回一个函数,该函数将加倍并加二。这个函数在typescript中应该怎么打(当前定义只返回Function)?

declare function flow<In, Intermediate, Out>(f1: (a1: In) => Intermediate, f2: (a1: Intermediate) => Out): (a1: In)=> Out 适用于两个函数,第一个函数有一个输入参数。我不确定如何扩展定义以适用于所有情况。

如果这样调用,我的尝试可以支持多个函数:

lodash.flow(f1, lodash.flow(f2, f3))

但我正在寻找

lodash.flow(f1, f2, f3)

【问题讨论】:

  • 谁能告诉我为什么这被否决了?如果错了,能改正吗?

标签: javascript typescript lodash


【解决方案1】:

我不相信你能写出这样的定义。

如果我们查看the lodash type declaration file,他们不会试图表达这种关系。

interface LoDashStatic {
    flow<TResult extends Function>(...funcs: Function[]): TResult;
}

但仅凭这一点还不足以否定这种可能性。作者可能只是忽略了一些东西,所以让我们继续思考吧。

单个函数链之间的关系是您可以表示的。您在上面的示例中已经这样做了。您可以为多个参数长度创建相同想法的手动版本,但这是因为您设置的情况是链的长度已知并且您可以授予单独的类型信息。

如果我们要处理可变长度参数的情况,我们必须将参数视为一个集合。因为所有变量都必须有一个单一的(尽管可能是参数化的)类型,所以这个集合对象也必须有。但是,各种功能的类型并不一致。 (param:A) =&gt; B(param:B) =&gt; C 的类型不同,并且不能存储在同一个类型良好的容器中(除了联合类型,但它们也不会扩展)。

在您希望在这样的参数列表中保留类型信息的情况下,您通常在两个参数上定义组合函数并将其应用于多个函数。例如,这就是在 Promise 中保留类型信息的方式。为此,您仍然需要详细说明每个单独的参数。它只是让你最终得到正确的输出类型。也就是说,在大多数情况下,这就是您想要的,所以一切都很好。

如果 lodash 是用类型良好的函数式语言编写的,那么该流函数可能就不存在了。我想它会被写成一个管道组合对象。

更新:我说的“管道组合对象”是什么意思?可能是这样的:

class FunctionComposer<T,V> {
    constructor(protected func: (param: T) => V) { }

    public compose<X>(newFunc: (param:V) => X) {
        return new FunctionComposer((x: T) => newFunc(this.func(x)));
    }
    public out() {
        return this.func;
    }
}

let composedFunc = new FunctionComposer((x: number) => x * 2)
    .compose(x => x.toString())
    .out();

// composedFunc has type (param:number) => string

【讨论】:

  • 什么是管道组合对象?
  • @2426021684 我用我刚刚准备好的答案更新了我的答案。这有帮助吗?
【解决方案2】:

这是一种使用conditional types 的方法:

const compose =
  <T1, T2>(f1: (p: T1) => T2) =>
  <T3>(f2: (p: T2) => T3) =>
  (p: T1) =>
    f2(f1(p));

const flow = <T1, T2, T3 = "♘", T4 = "♘">(
  f0: (p: T1) => T2,
  ...f: [] | [(p: T2) => T3] | [(p: T2) => T3, (p: T3) => T4]
): ((p: T1) => T3 extends "♘" ? T2 : T4 extends "♘" ? T3 : T4) => {
  if (f[1]) {
    return compose(compose(f0)(f[0]!))(f[1]) as any;
  }

  if (f[0]) {
    return compose(f0)(f[0]) as any;
  }

  return f0 as any;
};

在本例中,flow 最多支持 3 个 args,但可以扩展到任意数量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-02
    • 2017-11-03
    • 2023-04-01
    • 1970-01-01
    • 2019-03-21
    • 2016-08-28
    • 2022-08-05
    • 2020-10-15
    相关资源
    最近更新 更多