【问题标题】:Flow Type refinement by checking for existing properties通过检查现有属性来细化流类型
【发布时间】:2018-11-25 02:28:44
【问题描述】:

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

【问题讨论】:

  • 你没有在你的类型中声明这个属性:playlist_name, category_name

标签: javascript flowtype flow-typed


【解决方案1】:

您可以创建这种效果,在 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 在您的代码中不起作用,因为例如,TimeLineStatsType 具有 rank_in_week 键是有效的。 Flow 无法通过检查 rank_in_week 的存在来优化类型。

【讨论】:

  • 感谢您的建议,我“简单”地将所有类型转换为使用管道符号的精确对象。我很困惑为什么这不是默认模式......
  • 我同意一遍又一遍地输入这些管道会让人厌烦,而且很容易忘记它们。像所有 Flow 一样,它的类型系统旨在逐步应用于代码库。我想最初启用额外属性会使采用 Flow 变得更容易。如果可以通过 .flowconfig 为整​​个项目启用确切的对象,那就太好了。
  • 奇怪的是,Flow 团队今天 (2018-10-16) 宣布,他们计划在 Flow 中默认设置“精确”对象。他们有一个关于如何启用它的详细时间表:medium.com/flow-type/…
猜你喜欢
  • 2018-01-11
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多