在带有流类型的js中键入管道函数

Typing a pipe function in js with flow type

所以我用flow输入的js中有如下管道函数:

const pipe = (...fns: $ReadOnlyArray<any>): any => (param: any) => fns.reduce((result, fn) => fn(result), param)

我希望可能允许 some 键入并使用 mixed 类型,如下所示:

const pipe = (...fns: $ReadOnlyArray<mixed>): mixed => (param: mixed) => fns.reduce((result, fn) => fn(result), param)

但是flow给出错误信息:

flow: error infer - fn (Cannot call 'fn' because mixed [1] is not a function.)

在线查看:https://flow.org/try/#0PTAEAEDMBsHsHcBQBjWA7AzgF1ABwJa4CmoAvKABQB0NkmAXKACQBKRAhgCYDya0AngEEATsPb8APOzT8AfAEpG0-mVmVc7MQFslM+atB0MVYUU4BXZEQoVTGc9CwAaQ2n2k1dW0XuP5LjW15RBR0bDxCIgAmMkoaKiNGVg4ePiFRcQktfAAPMwVGbLzOAwpA9h1QIrN3T0wTM0trb19nV1rXFocsfzxNCvkgA

非要用any类型还不算世界末日,但我想知道为什么我不能用mixed类型?我的意思是它可以根据文档使用函数:https://flow.org/en/docs/types/mixed/

根据定义,该函数接受任意数量的参数,可以是任何参数。是的,这包括功能,但它也包括,例如,数字。如果你调用 pipe(5) 会发生什么?

相反,您似乎只想将其限制为函数。这很简单——只需将 $ReadOnlyArray<mixed> 替换为 ReadOnlyArray<mixed => mixed>。通过该更改,函数类型检查。

但是,这仍然不是一个非常有用的类型。使用结果会令人沮丧,因为它是 mixed。这意味着 Flow 对其类型一无所知,因此您将被迫在使用它之前对其进行优化。而且,运行时改进只能到此为止。

如果这个函数是多态的,它会更有用:

const pipe = <T>(...fns: $ReadOnlyArray<T => T>): (T => T) => {
  return (param) => {
    return fns.reduce((result, fn) => fn(result), param);
  };
}

function plus5(x) { return x + 5; }
function times3(x) { return x * 3; }
const plus5times3 = pipe(plus5, times3);

(plus5times3(6): number);
// expected error
(plus5times3(6): string);

(playground)

现在,您可以实际调用它并获得有用的结果。正如所写的那样,您有时可能会由于类型推断而遇到令人困惑的类型错误,但这通常可以通过添加额外的类型注释来解决。特别是我建议在 compose 的结果中添加类型注释,例如

const plus5times3: number => number = pipe(plus5, times3);