如何在 Flow 中指定 Moment.js 对象注解

Posted

技术标签:

【中文标题】如何在 Flow 中指定 Moment.js 对象注解【英文标题】:How to specify a Moment.js object annotation in Flow 【发布时间】:2017-08-19 14:00:41 【问题描述】:

我目前正在通过将 Flow 应用于现有项目并将函数参数注释为 Moment.JS 对象来学习 Flow。

使用 flow-typed 我能够为 Moment.JS 安装一个库定义,它似乎具有我正在寻找的类型:

declare class moment$Moment 
  static ISO_8601: string;
  static (string?: string, format?: string|Array<string>, locale?: string, strict?: bool): moment$Moment;
  static (initDate: ?Object|number|Date|Array<number>|moment$Moment|string): moment$Moment;
  static unix(seconds: number): moment$Moment;
  static utc(): moment$Moment;
  ...

但是,当我尝试将函数参数注释为 Moment.JS 对象时,Flow 无法识别它们。在以下函数中startDateendDate 是 Moment.JS 日期对象。

const filterByDateWhereClause = (startDate: Moment, endDate: Moment): string => ...;

Flow 给出以下错误:

const filterByDateWhereClause = (startDate: Moment, endDate: Moment): string =>
                                                 ^^^^^^ identifier `Moment`. Could not resolve name

这甚至可以通过 Flow 实现吗?或者我是否需要复制 Moment.JS 对象的 type 与 flow-type 提供的库定义中的对象相同?我不想这样做,因为 libdef 相当长。

例如:

declare class Moment 
  static ISO_8601: string;
  static (string?: string, format?: string|Array<string>, locale?: string, strict?: bool): moment$Moment;
  static (initDate: ?Object|number|Date|Array<number>|moment$Moment|string): moment$Moment;
  static unix(seconds: number): moment$Moment;
  static utc(): moment$Moment;
  ...

const filterByDateWhereClause = (startDate: Moment, endDate: Moment): string => ...;

我错过了什么?

【问题讨论】:

【参考方案1】:

有三种方法可以得到你想要的类型。

如果您的文件已经需要 moment 作为模块,您应该可以使用该类型

import moment from 'moment';

const filterByDateWhereClause = (startDate: moment, endDate: moment): string => ...;

或者如果您不使用源代码而只使用文件中的类型。

import type Moment from 'moment';

const filterByDateWhereClause = (startDate: Moment, endDate: Moment): string => ...;

您可以这样做,因为这是 libdef 指定为模块导出的内容: https://github.com/flowtype/flow-typed/blob/7822da72587078a4b8e0f2b56746d0da41a3ddde/definitions/npm/moment_v2.x.x/flow_v0.34.x-/moment_v2.x.x.js#L233

另外,libdef 似乎也在全局命名空间中声明了一个类型 moment$Moment,因此您可以使用它。

const filterByDateWhereClause = (startDate: moment$Moment, endDate: moment$Moment): string => ...;

我不推荐全局使用,因为它不太明确类型来自哪里。

【讨论】:

moment$Moment 对我不起作用,可能是因为我使用的是 Webpack,所以没有全局命名空间?这两种导入方法都有效。 Webpack 不应该对流的运行方式产生影响——我不确定为什么全局类型不适合你,但这很好,因为你不应该真正使用它......在流类型的 CONTRIBUTING.md 文档中,它告诉 libdef 作者为不应该是全局的全局变量添加前缀:(github.com/flowtype/flow-typed/blob/…),所以无论如何你都不应该使用它:)【参考方案2】:

似乎从对象创建一个子类解决了这个问题:

import moment from 'moment';

class Moment extends moment 

const filterByDateWhereClause = (startDate: Moment, endDate: Moment): string => ...;

仍然有兴趣知道这是否是注释 Moment.JS 对象的正确方法。

【讨论】:

以上是关于如何在 Flow 中指定 Moment.js 对象注解的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript 中指定定义为对象文字的箭头函数的类型?

如何使用 protobuf-net 反序列化 .asmx webservice 中指定的对象

使用moment.js解析时如何忽略时区

如何在 map 函数中指定数据类型?

如何输出分组对象中指定列中所有值的列表

如何在 moment.js 持续时间内使用 format()?