2017-03-08 30 views
0

我有这样的代码:场景,流量工程解构函数参数,但不能用于非解构后的参数

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

myFunctionwrapper做同样的事情myFunction2wrapper2,对不对?但流动认为有后者复制(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

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

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

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

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

tryflow

在第二个函数调用,流问题这个错误:

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},因为它知道没有其他人持有对它的引用。