通过检查现有属性来细化流类型

Flow Type refinement by checking for existing properties

下面是try flowtype

中给出的例子
export type TimeLineCourseType = {
    date: string,
    done: boolean,
    category_name: string,
};

export type TimeLineCatType = {
    date: string,
    done: boolean,
    rank_in_week: number,
};

export type TimeLineStatsType = {
    date: string,
    timespan: string
};

const displayTimelineItem = (item: TimeLineCourseType | TimeLineCatType | TimeLineStatsType, i: number) => {
    if (item.category_name) {
        return (
            item.playlist_name,
            item.category_name
        );
    } else if (item.rank_in_week) {
        return (
            item.rank_in_week
        );
    } else {
        return (item.timespan);
    }
};

从 if else 块中可以清楚地看出,每个块中的项目只能是一种特定类型,而不是全部三种。但是我收到流程错误。同样使用 hasOwnProperty 也无济于事。有什么解决办法吗?

您可以创建这种效果,称为 disjoint union in Flow, by either adding a common key to all types and refining based on its value or switching to using exact types

下面是一个使用 type 键进行优化的示例:

export type TimeLineCourseType = {
  date: string,
  done: boolean,
  category_name: string,
  type: 'TimeLineCourseType',
};

export type TimeLineCatType = {
  date: string,
  done: boolean,
  rank_in_week: number,
  type: 'TimeLineCatType',
};

export type TimeLineStatsType = {
  date: string,
  timespan: string
  type: 'TimeLineStatsType',
};

const displayTimelineItem = (item: TimeLineCourseType | TimeLineCatType | TimeLineStatsType, i: number) => {
  if (item.type === 'TimeLineCourseType') {
    return (
      item.playlist_name, 
      item.category_name
    );
  } else if (item.type === 'TimeLineCatType') {
    return (
      item.rank_in_week
    );
  } else {
    return (item.timespan);
  }
};

或者您可以继续使用您的方法,将类型 "exact" objects 与管道、{| |} 放在大括号内:

export type TimeLineCourseType = {|
  date: string,
  done: boolean,
  category_name: string,
|};

export type TimeLineCatType = {|
  date: string,
  done: boolean,
  rank_in_week: number,
|};

export type TimeLineStatsType = {|
  date: string,
  timespan: string
|};

const displayTimelineItem = (item: TimeLineCourseType | TimeLineCatType | TimeLineStatsType, i: number) => {
  if (item.category_name) {
    return (
      item.playlist_name, 
      item.category_name
    );
  } else if (item.rank_in_week) {
    return (
      item.rank_in_week
    );
  } else if (item.timespan) {
    return (item.timespan);
  }
};

管道使这项工作起作用,因为由于 Flow 中的 width subtyping,允许对象具有 "extra" 键。 Flow 在您的代码中不起作用,因为例如 TimeLineStatsType 具有 rank_in_week 键是有效的。 Flow 无法通过检查是否存在 rank_in_week.

来细化类型