流程:检查类型

时间:2016-08-18 12:40:15

标签: javascript flowtype

我有一个函数接受一个thenable(一个具有then()方法的对象;请参阅MDN JavaScript docs: Promise.resolve()的顶部)或其他:

function resolve<T>(value: {then: ()=>T}|T) {
    if (value && value.then) {
        console.log('thenable', value.then);
    } else {
        console.log('not thenable');
    }
}

Try Flow demo

当我在此value.then语句中访问if时,流程会抱怨。我可以用(value: any).then修复它,但这看起来很糟糕。

有人可以推荐一种很好的方式来检查吗?

1 个答案:

答案 0 :(得分:5)

好问题!这是Flow团队在过去几周里一直在努力的事情!

有什么问题

if (value && value.then) {
  // What is the type of `value` here?
} else

在if语句中,value的类型是什么?如果Tstring,那么它将是{then: ()=>T},正如您所期望的那样。但是如果T{ then: string }怎么办?据我们所知,T可能有一个名为then的属性!

Flow小组正在做什么来解决这个问题?

  • 添加确切的对象类型。这个问题来自于不知道联盟的一个分支是否具有属性。使用精确类型,您可以准确地告诉Flow对象具有哪些属性。
  • 允许value.then属性检查,并将value.then的类型细化为mixed

很多这项工作已经掌握了。您可以查看当前以master为主的flowtype.org/try。 Your example on flowtype.org/try

一旦这些东西出现(一些来自v0.31.0,一些来自v0.32.0),我们将对其进行文档和博客。

编辑:添加更多信息

3个主要问题

我们正在解决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确定只有union类型的一个分支可以工作,它将优化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很难说对象类型DOESN&t; T具有属性。所以我们正在添加确切的类型。

{| 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;
  }
}

一旦我们推出这些,我们就会记录它们!所以保持你的眼睛去皮!