Momentjs和Flow类型

时间:2019-03-15 23:49:49

标签: javascript momentjs flowtype

我正在尝试学习如何使用流程,但是我陷入了一条错误消息,该消息对我来说毫无意义。

这是我的代码:

import moment from "moment-timezone";
import type MomentType from "moment-timezone";

type filtersType = {
  page?: number,
  ccaa?: string,
  province?: string,
  date_from?: MomentType,
  date_to?: MomentType,
  distance_from?: number,
  distance_to?: number,
  category?: Array<string>,
};

const _parseValue = (value: mixed): string => {
  if (Array.isArray(value)) return value.join(",");
  else if (moment.isMoment(value)) return value.toISOString();
  else if (typeof value === "number") return value.toString();
  else if (typeof value === "string") return value;
  throw new Error("Filter value type is not valid!!");
};

const _generateQueryItem = (key: string, value: mixed): string => {
  return `${key}=${_parseValue(value)}`;
};

const _generateQuery = (filters: filtersType): string => {
  return Object.entries(filters)
    .map(([key, value]) => _generateQueryItem(key, value))
    .join("&");
};

它在第33行上一直对此抱怨:

Cannot call value.toISOString because property toISOString is missing in mixed [1].                

 [1] 30│ const _parseValue = (value: mixed): string => {
     31│   console.log(moment.isDate(value));
     32│   if (Array.isArray(value)) return value.join(",");
     33│   else if (moment.isMoment(value)) return value.toISOString();                            
     34│   else if (typeof value === "number") return value.toString();                            
     35│   else if (typeof value === "string") return value;
     36│   throw new Error("Filter value type is not valid!!");                                    

尽管混合类型包含了所有内容,但我总是这样,它不应该抱怨缺少任何方法,我不确定发生了什么,我试图将args类型更改为:

const _parseValue = (value: mixed | MomentType): string => {

和:

const _generateQueryItem = (key: string, value: mixed | MomentType): string => {

但我仍然遇到相同的错误。

我需要一种让流程知道value具有toISOString方法的方法,但是今天我的想法已经用完了。我该怎么办?

(我已经安装了流程类型为btw的矩类型)

1 个答案:

答案 0 :(得分:1)

啊,type refinement

因此,您正在尝试优化value的类型。您正在执行此操作:

if (typeof value === "number") return value.toString();

检查value是否为数字。 Flow会理解这一点,并将value细化为一个数字,以便您可以在其上调用toString

您正在这样做:

if (Array.isArray(value)) return value.join(",");

检查value是否为数组。 Flow理解了这一点,并将value精简为一个数组,因此您可以在其上调用join

您正在这样做:

if (moment.isMoment(value)) return value.toISOString();

检查value是否是矩对象的实例。 Flow不会(em> not )将此理解为一种改进。因此,您的类型没有得到改进,因此当您尝试调用toISOString时,流程会告诉您mixed上不存在您的方法。

Flow仅支持一小部分但功能强大的优化操作。甚至不知道isMoment只是作为一种改进。可以从mixed提炼的唯一值实际上是原始的旧数据值,数字,字符串,数组,对象,无法从mixed提炼为MomentType

首先,让我们停止依赖mixed。如果您只能接收一小部分类型的可解析值,则union将为您提供更好的服务,并且将显式添加MomentType作为改进的可能性:

type Parseable = number | string | string[] | MomentType;

这就是我们暂时优化对象的问题。好吧,我们有两种可能性。如果我们真的真的只关心这些类型,这意味着我们完全有信心这些是我们将要获得的唯一东西,那么我们甚至不必显式地优化为矩对象:

const _parseValue = (value: Parseable): string => {
  if (Array.isArray(value)) return value.join(",");
  else if (typeof value === "number") return value.toString();
  else if (typeof value === "string") return value;

  return value.toISOString(); // by process of elimination, this is a moment
};

Flow足够聪明,可以知道我们已经处理了所有其他情况,因此,如果我们到达函数的末尾,那么通过消除value的过程一定是片刻。

那么,我们应该依靠这种行为吗?这得看情况。是否可以将来自不可靠API的任意数据传递到_parseValue中?还是来自流程类型代码库中可靠位置的良好类型数据?如果我们不需要过多担心虚假数据,那么可以肯定地依靠消除过程。否则,我们可能应该保留您原来的错误情况。但这意味着我们必须显式优化我们的矩类型:

const _parseValue = (value: Parseable): string => {
  if (Array.isArray(value)) return value.join(",");
  else if (typeof value === "number") return value.toString();
  else if (typeof value === "string") return value;
  // let's be extra careful
  else if (typeof value === 'object' && value.isMoment && value.toISOString) return value.toISOString();
  throw new Error("Filter value type is not valid!!");
};

Flow将接受我们的支票typeof value === 'object',足以将valueParseable中的其他条目区分开并确保它是MomentType,但是由于我们的数据源可能值得怀疑的是,我们还检查一下value.isMoment(当前在流类型的libdef中定义的所有矩对象的属性)。毫无疑问,这应该证明这实际上是一个瞬间的对象。一种策略是只对我们拥有value.toISOString的对象进行鸭子式输入并继续对其进行调用。