给定以下类型:
/* @flow */
type Vehicle = {
make?: string,
model?: string,
};
const vehicle: Vehicle = {
make: 'Ford',
model: 'Focus',
};
如果我想确保在使用它们之前定义了make
和model
属性,我希望以下工作:
const hasAttributes = vehicle.make && vehicle.model;
if (hasAttributes) {
console.log(`${vehicle.make} ${vehicle.model}`);
}
然而,流量抛出一个错误,说make
和model
可能是未定义的,因此无法强制转换为字符串。
但是这段代码确实有效:
if (vehicle.make && vehicle.model) {
console.log(`${vehicle.make} ${vehicle.model}`);
}
这是一个错误还是我错过了什么?这是playground example。
这里有两个警告。首先,最明显的是这条线......
const hasAttributes = vehicle.make && vehicle.model;
......这不符合你的预期。而不是返回true
或false
,&&
运营商returns either the first operand, if it's falsy, or the last one。这就是为什么在你的情况下hasAttributes
值永远不会严格等于true
(因为make
和model
属性都是字符串)。但是对于=== true
,你要检查严格的平等。
具有讽刺意味的是,Flow没有发现这个故障 - 因为它不是它的任务。但是你可以使它更明确,例如:
const hasAttributes = vehicle.make && vehicle.model;
(hasAttributes: boolean);
......现在你会看到相应的警告。解决方案相当简单:
const hasAttributes = Boolean(vehicle.make && vehicle.model);
不过,它不会解决另一个真正的问题。 Flow正在发现undefined
值的潜在输出,因为在这些情况下它有些悲观。在Flow的Github上有一个完整的slew of similar issues。
关键是,使用单独的变量会混淆检查器。这就是为什么两个完全相同的片段:
const hasAttributes = vehicle.make && vehicle.model;
if (hasAttributes) { // output vehicle
......而且......
if (vehicle.make && vehicle.model) { // output vehicle
......被区别对待。