确定对象是否具有属性

时间:2017-12-30 11:55:58

标签: flowtype

给出以下类型:

/* @flow */

type Vehicle = {
  make?: string,
  model?: string,
};

const vehicle: Vehicle = {
  make: 'Ford',
  model: 'Focus',
};

如果我想确保在使用它们之前定义了makemodel属性,我希望以下方法能够正常工作:

const hasAttributes = vehicle.make && vehicle.model;
if (hasAttributes) {
  console.log(`${vehicle.make} ${vehicle.model}`);
}

然而,流程会抛出错误,指出makemodel可能未定义,因此无法强制转换为字符串。

此代码确实有效:

if (vehicle.make && vehicle.model) {
  console.log(`${vehicle.make} ${vehicle.model}`);
}

这是一个错误还是我错过了什么?这里' S playground example

1 个答案:

答案 0 :(得分:0)

这里有两个警告。首先,最明显的是这条线......

const hasAttributes = vehicle.make && vehicle.model;

......这不符合你的预期。而不是返回truefalse&&运算符returns either the first operand, if it's falsy, or the last one。这就是为什么在您的情况下hasAttributes值永远不会严格等于true的原因(因为makemodel属性都是字符串)。但是使用=== 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

......的处理方式不同。