lodash.flow
结合了两个或更多功能。
lodash.flow(double, addTwo)
将返回一个将加倍的函数并添加两个。应该如何在打字稿中键入此函数(当前定义只返回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)
答案 0 :(得分:2)
我不相信你可以写出那个定义。
如果我们看the lodash type declaration file,他们就不会试图表达这种关系。
interface LoDashStatic {
flow<TResult extends Function>(...funcs: Function[]): TResult;
}
但仅凭这一点并不足以打折这种可能性。作者可能只是忽略了一些东西,所以让我们继续思考它。
单个功能链之间的关系是您可以表达的。你已经在上面的例子中这样做了。您可以为多个参数长度创建相同构思的手动版本,但这是因为您正在设置链的长度已知并且您可以授予单个类型信息的情况。
如果我们要处理可变长度参数的情况,我们必须将参数视为集合。因为所有变量必须具有单个(尽管可能是参数化的)类型,所以此集合对象也必须如此。但是,各种功能的类型不对齐。 (param:A) => B
与(param:B) => C
的类型不同,并且不能存储在同一个类型良好的容器中(除了联合类型,但这些类型也不会缩放)。
在您希望在此类参数列表中保留类型信息的情况下,通常会在两个参数上定义组合函数,并将其应用于多个函数。例如,这就是在承诺中保留类型信息的方式。为此,您仍然需要拼出每个单独的参数。它只是使它到最后你有正确的输出类型。也就是说,在大多数情况下,这就是你想要的,所以这一切都很好。
如果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