javascript - Momentjs 和 Flow 类型

标签 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!!");                                    

我一直认为混合类型包含所有内容,因此,它不应该提示缺少任何方法,我不确定发生了什么,我尝试将参数类型更改为:

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

和:

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

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

我需要一种方法让流程知道 valuetoISOString 方法,但我今天已经没有想法了。我该怎么做?

(顺便说一句,我已经安装了带有流类型的矩类型)

最佳答案

啊,type refinement .

因此,您正在尝试细化的类型。你正在这样做:

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将其理解为一种改进。因此,您的类型没有被细化,因此当您尝试调用 toISOString 时,流程会告诉您您的方法在 mixed 上不存在。

Flow 仅支持一小部分但功能强大的细化操作。它不知道 isMoment 甚至是一种改进。唯一可以从 mixed 细化的值流是真正普通的旧数据值、数字、字符串、数组、对象,不可能从 mixed 细化到 MomentType.

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

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

然后就是我们对 moment 对象进行细化的问题。嗯,我们有两种可能性。如果我们真的关心这些类型,这意味着我们完全有信心这些是我们唯一能得到的东西,那么我们甚至不需要显式地细化为一个时刻对象:

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 中?或者来 self 们流类型代码库中可靠位置的类型正确的数据?如果我们不需要太担心虚假数据,那么当然可以依靠消除过程。否则,我们可能应该保留您原来的错误情况。但这意味着我们必须明确地细化我们的时刻类型:

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 中定义的所有 moment 对象的属性)暂时)。这应该毫无疑问地证明这实际上是一个矩对象。一种策略是对我们获得的任何具有 value.toISOString 的对象进行鸭子类型,然后继续调用它。

关于javascript - Momentjs 和 Flow 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55192033/

相关文章:

javascript - 循环生成JSON

javascript - 我有一个在 iframe 内带有单选按钮的表单,将文本插入到父文本区域。 "Undefined"来到 texarea 而不是单选按钮值

javascript - express/node.js API 中的高效服务器端 JavaScript 内存管理

javascript - 当另一个字段中的值为 0 时,如何禁用复选框?

javascript - 流类型操作确实适用于对象引用

javascript - 精确的对象类型定义和解构

react-native - 在React Native上没有 Debug模式的情况下,瞬间格式的时间将变为无效日期

javascript - 我可以使用 Moment.js 分配 "now"的内容吗?

javascript - Moment.js 时区 - 输出时考虑处于不同时区的日期/时间

javascript - 如何使用 Flow 在 React 中添加多态属性