也许类型和可选对象属性在流中并不完全相同,并且并不总是兼容的。
首先让我们看一下Maybe Types 的文档链接:
也许类型接受提供的类型以及null 或undefined。所以?number 表示number、null 或undefined。
所以?number 基本上是number | null | undefined。
现在让我们看看您的对象类型链接from the docs:
除了它们的设置值类型之外,这些可选属性可以是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
}
}
所以基本上,Response.data 期待void | string,而您正试图用void | string | null 设置它。类型必须在某处更改才能成功完成操作。有多种可能的方法:
Option one,将 length 返回值更改为更具体。可能是最简单的:
function length(): void | string {
return undefined;
}
我们已经消除了data 成为null 的可能性,因此不再出现类型错误。
Option two,使 Response.data 成为可能的类型
如果他们都是可能的类型,那么问题就消失了。最小可能的变化是这个:
type Response = {
data?: string | null;
}
我们刚刚添加了Response.data 成为null 的可能性。现在它可以接受length的返回类型,类型匹配,没有错误。但这有点令人困惑,将null 与可选属性结合起来。我们可以这样做:
type Response = {
data: ?string,
}
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,还可能是关于如何处理可选类型与一般类型的风格选择。