Flow 抱怨类型不兼容,即使我先检查类型

Flow complains about type incompatibility even though I check type first

我已经编写了一个 React 下拉组件,我可以向其提供以下任一组件:

我的简单流程类型如下所示:

type DropdownMenuItemType = DropdownMenuIconAndTextType | string;

type DropdownMenuIconAndTextType ={
    text: string,
    icon?: React$Element<React$ElementType>;
}

以前版本的组件只支持字符串。添加元素以支持 texticon 是我正在实施的新功能请求。我不想对现有用户进行任何重大更改。

因此,在我的组件中,我尝试尝试转换任何提供的 string 并将其包装在 DropdownMenuIconAndTextType 中,以便所有内容最终都成为这种类型。已经 DropdownMenuIconAndTextType 的项目保持不变。

let Array<DropdownMenuItemType> originalItems = 
let Array<DropdownMenuIconAndTextType> convertedItems = [];
{'English', 'French', 'German', {text: 'Dutch', icon : <SomeIcon />}};
     items.forEach( (currItem: DropdownMenuItemType) => {
           if(typeof currItem === DropdownMenuIconAndTextType){
               convertedItems.push(currItem);
           }
           else {
               convertedItems.push({text: currItem.toString()});
           }

}); 

但是流程有一个错误:

  if(typeof currItem === DropdownMenuIconAndTextType){
               convertedItems.push(currItem);
  }

并且它说 currItem 仍然可以是 string 并且与 convertedItems 不兼容,尽管它被类型检查为 DropdownMenuIconAndTextType

在这种情况下我需要做什么来满足流量?提前致谢。

我相信你混淆了 Flow 的类型代码和 JS 代码之间的区别。

在类型签名内部,typeof returns 文字值的类型,如 here. In the JS code that exists at runtime, such as in your if statement, typeof will just tell you whether something is a string, object, etc., as described here 所述。因此,条件运算符的左侧将计算为 "string""object",而不是变量的实际 Flow 类型。

在你的条件右侧,你有 Flow 类型 DropdownMenuIconAndTextType,它只存在于类型检查时,不存在于运行时。我有点惊讶 Flow 没有因此给你一个错误。

尝试这样的事情:

  if(typeof currItem !== 'string'){
               convertedItems.push(currItem);
  }

这将检查运行时存在的值是字符串还是对象,这应该与 Flow 的类型优化一起使用。