流程:检查类型

ako*_*nsu 5 javascript flowtype

我有一个函数接受一个thenable(一个有一个then()方法的对象;参见MDN JavaScript文档Promise.resolve()的顶部:) 或其他东西:

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

试试Flow演示

当我value.then在此if声明中访问时,Flow会抱怨.我可以解决它,(value: any).then但这看起来很hacky.

任何人都可以推荐一种好的方法来检查这个吗?

Gab*_*evi 5

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

问题是什么

if (value && value.then) {
  // What is the type of `value` here?
} else
Run Code Online (Sandbox Code Playgroud)

在那个if语句里面,是什么类型的value?如果Tstring,那{then: ()=>T}就像你期望的那样.但是如果T是的话{ then: string }呢?据我们所知,T可能有一个名为的财产then!

Flow团队正在采取什么措施来解决这个问题?

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

很多这项工作已经掌握了.您可以查看当前以master为主的flowtype.org/try.您在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
Run Code Online (Sandbox Code Playgroud)

这对于惯用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!
Run Code Online (Sandbox Code Playgroud)

这有帮助,因为你可以写这样的东西:

type Foo = {| x: string |} | {| y: string |};

function test(arg: Foo): string | void {
  if (arg.x) {
    return arg.x;
  }
}
Run Code Online (Sandbox Code Playgroud)

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