首页 > 解决方案 > 为什么 flowtype 认为我的变量未定义?

问题描述

我有一个如下所示的流类型对象声明:

   type ProjectType = {
     // removed for brevity
     releases?: Array<ReleaseType>
   }

有时对象中不包含releases,所以当我想使用它时,我首先对其进行条件检查。所以在这里,稍后在我的代码中,我在这样的条件之后访问该数组:

   if (selectedProject
      && selectedProject.releases
      && selectedProject.releases.length) {
      majorReleasesSet = new Set(selectedProject.releases.map((release: ReleaseType): string => (
        release.major)));
      projectHasNoReleases = false;
      projectLatestMajorRelease = selectedProject.releases.slice(-1)[0].major;
      projectLatestMinorRelease = selectedProject.releases.slice(-1)[0].minor;
    }

但是flow不喜欢这样,抱怨:

Cannot call selectedProject.releases.slice because property slice is missing in undefined [1].

     components/TimeEntries/EntryForm.jsx
     123│         release.major)));
     124│       projectHasNoReleases = false;
     125│       projectLatestMajorRelease = selectedProject.releases.slice(-1)[0].major;
     126│       projectLatestMinorRelease = selectedProject.releases.slice(-1)[0].minor;
     127│     }
     128│
     129│     const projectLatestRelease = `${projectLatestMajorRelease}.${projectLatestMinorRelease}`;

我到底错过了什么?我尝试添加Array.isArray(selectedProject.releases)但流程仍然抱怨。Flow 在第 125 行和第 126 行都列出了错误。

标签: javascriptflowtype

解决方案


我想说的是,您做了一些可能有效的事情(运行映射函数、制作集合等)这一事实使 Flow 担心releases对象的属性可能已更改。运行函数后,Flow 基本上会丢弃您的任何改进。

这是您的代码示例,按原样抛出错误

解决此问题的最简单方法是将releases对象提取到单独的值中,并针对该值执行 null 检查。这样,Flow 可以确定它仍然不为空:

试试

// Mock this
type ReleaseType = {
  major: string;
  minor: string,
}

type ProjectType = {
  // removed for brevity
  releases?: Array<ReleaseType>
}

var selectedProject: ProjectType = {
  major: "foo",
  minor: "bar",
}

// Set up some variables for this example since I
// don't have any context on them
declare var majorReleasesSet: Set<any>;
declare var projectHasNoReleases: any;
declare var projectLatestMajorRelease: any;
declare var projectLatestMinorRelease: any;

// The `const {releases} = whateverObject` is the important part here
const {releases} = selectedProject || {};
if (releases && releases.length) {
  majorReleasesSet = new Set(releases.map((release: ReleaseType): string => (release.major)));
  projectHasNoReleases = false;
  projectLatestMajorRelease = releases.slice(-1)[0].major;
  projectLatestMinorRelease = releases.slice(-1)[0].minor;
}

推荐阅读