流程抱怨 reduce 返回单个布尔值

Flow complaining about reduce returning a single boolean

我不确定我做错了什么:

export function subscriptionsReady(handles: Array<Object>): boolean {
  if (handles.length === 1) return handles[0].ready();

  return handles.reduce((a: any, b: Object): boolean => {
    return (typeof a === 'object' ? a.ready() : a) && b.ready();
  });
}

流程错误:

  9:   return handles.reduce((a: any, b: Object): boolean => {
              ^ call of method `reduce`
  9:   return handles.reduce((a: any, b: Object): boolean => {
              ^ undefined (too few arguments, expected default/rest parameters). This type is incompatible with the expected return type of
  6: export function subscriptionsReady(handles: Array<Object>): boolean {
                                                                 ^^^^^^^ boolean

查看 https://github.com/facebook/flow/blob/master/lib/core.js#L204(声明 Array#reduce 的重载签名):

当您省略 reduce 的第二个参数时,reduce 调用(以及传递给它的闭包)的 return 类型必须匹配元素类型 Object.由于您将其设为 boolean,因此您必须传入类型为 boolean.

的初始值

您的代码依靠动态检查来区分这两种情况,但这对于 Flow 来说太聪明了。

这是因为 type definition for Array.prototype.reduce 期望 "memo" 或返回的布尔值将第二个参数匹配到 .reduce().

不过,您似乎实际上是在尝试检查句柄中的每个对象是否 .ready(),在这种情况下,这可能对您更好:

function subscriptionsReady(handles: Array<Object>): boolean {
  return handles.every((handle): boolean => {
    return handle.ready();
  });
}

因为 Array.prototype.every 已经很好地输入了,你实际上可以省略其中的大部分类型:

function subscriptionsReady(handles: Array<Object>) {
  return handles.every(handle => handle.ready());
}

Flow 将能够推断出一切。

此外,您可能希望为句柄添加基本类型而不是 object,如下所示:

type Handle = { ready(): boolean };

function subscriptionsReady(handles: Array<Handle>) {
  return handles.every(handle => handle.ready());
}

这将改善当您误用 api 时 Flow 生成的错误。

一般来说,您应该尝试定义这些类型,而不是使用 Object