不能 return object literal 因为 null 或 undefined - Flow

Cannot return object literal because null or undefined - Flow

将 mayBe 类型与对象文字的可选属性混合

 type Response = {
        data?: string;
    }

 function length(): ?string {
      return undefined;
 }

 function test(): Response {
    const data = length()
    return {
        data
    }
 }

12:         data        ^ Cannot return object literal because null or undefined [1] is incompatible with string [2] in property `data`.
References:
5: function length(): ?string {
                      ^ [1]
2:     data?: string;
              ^ [2]

Test Flow

遵循 MayBe types and Object Types 的流程文档 我不确定为什么会收到错误消息,有没有办法解决这个问题?

也许类型和可选对象属性在流程中并不完全相同,并不总是兼容。

首先让我们看看您的文档 link Maybe Types:

Maybe types accept the provided type as well as null or undefined. So ?number would mean number, null, or undefined.

所以 ?number 基本上是 number | null | undefined.

现在让我们看看您的对象类型 link from the docs:

In addition to their set value type, these optional properties can either be void or omitted altogether. However, they cannot be null.

所以如果我们 type Response { data?: string } 那么 response.data 基本上是 string | void。请注意 void 是与 null.

完全不同的类型

那么现在让我们分解你的例子:

type Response = {
  data?: string; // void | string
}

function length(): ?string { // void | string | null
  return undefined;
}

function test(): Response {
  const data = length()
  // at this point, as far as flow knows, `data` can be `void`, `string`, or
  // `null`, and we're trying to set it as the `data` property on our
  // `Response` type which expects a `void` or a `string`, and does not
  // expect a `null`.
  return {
    data
  }
}

所以基本上,Response.data 期待 void | string,而您正试图用 void | string | null 设置它。类型必须在某处更改才能使您成功完成操作。有多种可能的方法:

Option one,将 length return 值更改为更具体。可能是最简单的:

function length(): void | string {
  return undefined;
}

我们消除了 data 成为 null 的可能性,因此不再有类型错误。

Option two,使Response.data成为可能类型

如果它们都是 maybe 类型,问题就迎刃而解了。最小的可能变化是这个:

type Response = {
    data?: string | null;
}

我们刚刚添加了 Response.data 成为 null 的可能性。现在可以接受length的return类型,类型匹配,不报错。但这有点令人困惑,将 null 与可选的 属性 组合在一起。我们可以这样做:

type Response = {
    data: ?string,
}

Option three,细化类型:

function test(): Response {
  const data = length()
  // at this point response.data is `void`
  const response = {};
  if (data) {
    // data is now a `number`, not `number | void | null`
    response.data = data;
  }
  // response.data is now `number | void` (not `null`)

  return response
}

无论手头的问题是什么,使用这些选项中的哪一个选项几乎完全取决于最好的 API,也可能是关于如何处理可选类型与一般类型的风格选择。