Flow适用于析构函数参数的场景,但不适用于非析构函数参数

时间:2017-03-08 19:55:06

标签: javascript flowtype

我有这段代码:

function myFunction({x}: {x?: number} = {}) {
    console.log(x);
    return 'foo';
}

function wrapper({x}: {x: number}) {
    return myFunction({x});
}

function myFunction2({x}: {x?: number} = {}) {
    console.log(x);
    return 'foo';
}

function wrapper2(args: {x: number}) {
    return myFunction2(args);
}

myFunctionwrappermyFunction2wrapper2完全相同,对吧?但是Flow认为后一个副本中存在错误(live demo)

16:   return myFunction2(args);
                         ^ object type. This type is incompatible with the expected param type of
10: function myFunction2({x}: {x?: number} = {}) {
                              ^ object type

这是一个错误,还是我遗漏了一些东西,这两个例子不相同?

1 个答案:

答案 0 :(得分:1)

这是一个较小的例子,说明了同样的问题:

function myFunction({x}: {x?: number} = {}) {
  console.log(x);
  return 'foo';
}

const x: number = 5;
const obj: {x: number} = {x};

myFunction({x});
myFunction(obj);

tryflow

在第二个函数调用中,Flow发出此错误:

10: myFunction(obj);
               ^ object type. This type is incompatible with the expected param type of
1: function myFunction({x}: {x?: number} = {}) {
                            ^ object type

这种情况发生的原因与解构无关。它只是因为对象是可变的,所以如果它们是不可变的,那么子类型规则并不像你期望的那样适用。

当对myFunction的调用进行类型检查时,Flow只查看类型签名,而不是实现。因此,就Flow而言,myFunction可以获取传递它的可变对象,并将其x属性设置为null。如果调用者认为x属性绝不能是null,则会违反其假设。

在第一个函数调用中,我们构造了一个全新的对象,因此Flow可以安全地推断出它具有类型{x?: number},因为它知道没有其他人持有对它的引用。