首页 > 解决方案 > 真实检查后访问可选道具的流程错误

问题描述

流 0.67.1(但行为在 0.73.1 中继续存在)

例子:

type PropOptional = {
  prop?: ComplexType
};                         

type ComplexType = {
  callable: () => void,
  anotherCallable: () => void
};

function usePropOptional(arg1: PropOptional) {
  if (arg1.prop) {
    arg1.prop.callable();
    arg1.prop.anotherCallable();
    arg1.prop.callable();
  }
};

arg1.prop该函数在访问 上的任何属性之前检查是否存在arg1.prop。这应该足以验证arg1.prop已定义。

Flow 在第一次arg1.prop访问属性时很好,这是对块arg1.prop.callable()内第一行的调用。if但是,流在随后尝试访问arg1.prop完全相同的if块中的属性时会产生错误:

arg1.prop.anotherCallable();
arg1.prop.callable();

我被迫在每一行前面加上一个死记硬背的arg1.prop &&真实性检查,或者重新分配arg1.prop给 if 块内的一个局部变量:

function usePropOptional(arg1: PropOptional) {
  if (arg1.prop) {
    const reallyExists = arg1.prop;
    reallyExists.callable();
    reallyExists.anotherCallable();
    reallyExists.callable();
  }
};

这感觉不对。我做错了什么或错过了什么?

您可以在 flow.org 上的 flow repl中检查这一点。

标签: javascriptflowtype

解决方案


这记录在 FlowType 的类型优化部分:

细化失效

也可以使细化无效,例如:

// @flow
function otherMethod() { /* ... */ }

function method(value: { prop?: string }) {
  if (value.prop) {
    otherMethod();
    // $ExpectError
    value.prop.charAt(0);
  }
}

这样做的原因是我们不知道 otherMethod() 没有对我们的价值做任何事情。...

有一种简单的方法可以解决这个问题。在调用另一个方法之前存储该值并改用存储的值。这样,您可以防止细化失效。

// @flow
function otherMethod() { /* ... */ }

function method(value: { prop?: string }) {
  if (value.prop) {
    var prop = value.prop;
    otherMethod();
    prop.charAt(0);
  }
}

因此,在您的最终情况下,解决方法似乎是避免此问题的建议方法。


推荐阅读