【问题标题】:Flow: check type of thenable流程:检查thenable的类型
【发布时间】:2016-12-25 09:39:59
【问题描述】:

我有一个函数可以接受 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

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

谁能推荐一个好方法来检查这个?

【问题讨论】:

    标签: javascript flowtype


    【解决方案1】:

    好问题!这是 Flow 团队在过去几周一直在努力解决的问题!

    有什么问题

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

    在 if 语句中,value 的类型是什么?如果Tstring,那么它将是{then: ()=&gt;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 &amp;&amp; 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;
      }
    }
    

    一旦我们推出这些,我们就会记录下来!所以请擦亮眼睛!

    【讨论】:

    • 谢谢。我关于 flowtype 的示例与我发布的原始示例相同。您说通过这些新更改,我将能够指定确切的类型,但是这个示例没有任何新内容,但它仍然进行类型检查。我是不是听错你说的了?
    • 我写的有点匆忙,所以我没有提供说明性的例子,但我会尽快解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 2018-06-30
    • 2016-06-16
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多