动态类型测试无法按预期工作 [英] dynamic type tests not working as expected
问题描述
这是 SSCCE .
我有一个地图容器类,其中使用第一个调用的set
方法按需创建内部Map
:
I have a map container class where an internal Map
is created on demand with the first set
method that gets called:
// @flow
'use strict';
class MapContainer {
map: ?Map<any, any>;
constructor() {
this.map=null;
}
set(key: any, value: any): ?any {
if (this.map===null) {
this.map = new Map();
}
let prevValue: ?any;
if (this.map!=null) { // first check
prevValue = this.map.get(key);
}
if (this.map!=null) { // second check
this.map.set(key, value);
}
return prevValue;
}
}
exports.MapContainer = MapContainer;
上面的代码在没有警告的情况下通过了npm run flow
.
The above code passes npm run flow
with no warnings.
但是,如果我将两个if (this.map!=null)
检查合并为一个:
However if I merge the two if (this.map!=null)
checks into one:
// @flow
'use strict';
class MapContainer {
map: ?Map<any, any>;
constructor() {
this.map=null;
}
set(key: any, value: any): ?any {
if (this.map===null) {
this.map = new Map();
}
let prevValue: ?any;
if (this.map!=null) { // merged check
prevValue = this.map.get(key);
this.map.set(key, value);
}
return prevValue;
}
}
exports.MapContainer = MapContainer;
…然后运行流失败,并显示以下消息:
… then running flow fails with the following message:
es6/map-container.js:19
19: this.map.set(key, value);
^^^^^^^^^^^^^^^^^^^^^^^^ call of method `set`. Method cannot be called on possibly null value
19: this.map.set(key, value);
^^^^^^^^ null
es6/map-container.js:19
19: this.map.set(key, value);
^^^^^^^^^^^^^^^^^^^^^^^^ call of method `set`. Method cannot be called on possibly undefined value
19: this.map.set(key, value);
^^^^^^^^ undefined
…这对第19行的访问毫无意义:
… which makes no sense at all as the access on line 19:
this.map.set(key,value)
…仍然被支票覆盖:
… is still covered by the check:
if (this.map!=null)
有什么作用?
推荐答案
问题是对get
方法的调用会使优化无效.如果get
将this.map
设置为null
怎么办?流量无法得知,因此假设情况最糟.这是您可以做的:
The problem is that call to get
method can invalidates refinement. What if get
sets this.map
to null
? Flow has no way of knowing, so it assumes the worst. Here is what you can do:
class MapContainer {
map: ?Map<any, any>;
constructor() {
this.map=null;
}
set(key: any, value: any): ?any {
if (!this.map) {
this.map = new Map();
}
const map = this.map;
let prevValue: ?any;
if (this.map!=null) {
prevValue = map.get(key);
map.set(key, value);
}
return prevValue;
}
}
这篇关于动态类型测试无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!