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

时间:2018-06-15 09:00:52

标签: javascript flowtype flow-typed

以下是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也无济于事。有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:2)

您可以在Flow中创建此效果,称为disjoint union,方法是向所有类型添加公用密钥,并根据其值进行优化或切换为使用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,对象被允许有"额外的"键。 Flow不会在您的代码中起作用,因为例如,TimeLineStatsTyperank_in_week密钥有效。 Flow无法通过检查是否存在rank_in_week来优化类型。