无法返回对象文字,因为 null 或未定义 - Flow

dus*_*awn 0 flowtype flow-typed

将 mayBe 类型与对象字面量的 Optional props 混合

 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]

Run Code Online (Sandbox Code Playgroud)

测试流程

按照MayBe 类型对象类型的流程文档, 我不确定为什么会出现错误,有没有办法解决这个问题?

Lyl*_*ood 5

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

首先让我们看一下您的Maybe Types文档链接:

也许类型接受提供的类型以及nullor undefined。所以?number将意味着number, null, 或undefined

?number基本上是这样number | null | undefined

现在让我们看看文档中的Object Types 链接:

除了它们的设置值类型之外,这些可选属性可以是void或完全省略。但是,它们不能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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

选项一,将length返回值更改为更具体。可能是最简单的:

function length(): void | string {
  return undefined;
}
Run Code Online (Sandbox Code Playgroud)

我们已经移除的可能性datanull,所以没有更多类型的错误。

选项二,做Response.data一个maybe类型

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

type Response = {
    data?: string | null;
}
Run Code Online (Sandbox Code Playgroud)

我们刚刚添加的可能性Response.datanull。现在它可以接受 的返回类型length,类型匹配,没有错误。但这有点令人困惑,将 thenull与 optional 属性结合起来。我们可以这样做:

type Response = {
    data: ?string,
}
Run Code Online (Sandbox Code Playgroud)

方案三,细化类型:

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
}
Run Code Online (Sandbox Code Playgroud)

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