好问题!这是 Flow 团队在过去几周一直在努力解决的问题!
有什么问题
if (value && value.then) {
// What is the type of `value` here?
} else
在 if 语句中,value 的类型是什么?如果T 是string,那么它将是{then: ()=>T},正如您所期望的。但是如果T 是{ then: string } 呢?据我们所知,T 可能有一个名为 then 的属性!
Flow 团队正在做些什么来解决这个问题?
- 添加精确的对象类型。这个问题来自于不知道工会的一个分支是否有财产。通过确切的类型,您可以准确地告诉 Flow 对象具有哪些属性。
- 允许
value.then 属性检查,并将value.then 的类型细化为mixed。
很多这样的工作已经在 master 中了。您可以查看 flowtype.org/try,它目前在 master 之外运行。 Your example on flowtype.org/try
一旦这些东西落地(有些出现在 v0.31.0 中,有些出现在 v0.32.0 中),我们将记录并写博客。
编辑:添加更多信息
三个主要问题
我们正在努力解决 3 个一般性问题。
- 我们什么时候应该在条件中允许
value.then?如果我们只在确定value 具有then 属性时才允许value.then,那么我们可以捕捉到value.tehn 之类的拼写错误。但是,惯用的 JavaScript 通常会测试对象的属性,这些属性可能存在也可能不存在。
- 如果条件为真或假,
value 的类型是什么。在提供的示例中,value 是联合类型。看起来value && value.then 的目的是检测函数是否使用联合的左分支。但是,Flow 无法安全地选择分支,因为 T 可能有一个 then 字段。
- 如果条件为真或假,
value.then 的类型是什么。同样,T 可能是像 { then: string } 这样的对象,所以 value.then 可能是任何东西
我们的解决方案
我们什么时候应该在条件中允许value.then
我们将始终允许value.then。这意味着我们不能轻易地捕捉到属性名称的拼写错误,但这意味着我们可以支持更惯用的 JavaScript。 Flow 的主要原则之一是它可以很好地与人们倾向于编写的 JavaScript 配合使用。
如果条件为真或假,value 的类型是什么。
如果 Flow 确定只有联合类型的一个分支可以工作,它会将 value 的类型细化为该分支。否则,value 将不会被细化。确切的类型将对此有所帮助
如果条件为真或假,value.then 的类型是什么
如果 Flow 确定只有一个 union 类型的分支可以工作,它会将 value.then 的类型细化为该分支上的 then 属性的类型。如果 Flow 确定没有分支具有该属性,它将出错。否则,它将使用mixed 类型。精确类型也有助于此。
什么是确切类型
{ x: string } 是具有属性x 的对象的类型,其类型为string。
var example1: { x: string } = { x: 'hello' }; // This is ok
var example2: { x: string } = { x: 'hello', y: 123 }; // This is also ok
这对于惯用的 JavaScript 很有用,但让 Flow 很难说对象类型没有属性。所以我们要添加确切的类型。
{| x: string |} 是具有属性x 的对象的类型,该属性的类型为string,但没有其他属性。
var example1: {| x: string |} = { x: 'hello' }; // This is ok
var example2: {| x: string |} = { x: 'hello', y: 123 }; // Error! Extra property y!
这很有帮助,因为你可以这样写:
type Foo = {| x: string |} | {| y: string |};
function test(arg: Foo): string | void {
if (arg.x) {
return arg.x;
}
}
一旦我们推出这些,我们就会记录下来!所以请擦亮眼睛!