使用TypeScript和MomentJS - moment()函数的返回类型是什么?

73

我目前正在将我的项目从ES5转换为ES6,但是在使用MomentJS(版本2.18.1)时遇到了问题。问题是我有一些变量是Moment对象,但我无法对它们调用moment()。

例如:

import * as moment from "moment";

export class DateThingy {

  constructor(private moment) { //What type does this have??
  }

  public getDate(): moment.Moment { 
    return this.moment();
  }
}

1) 如果我将 private moment 的类型设置为 private moment: moment,WebStorm 将会提示:"cannot find name 'moment'."。

2) 如果我将类型设置为 private moment: moment.Moment,该对象已经更改,我不能再调用 this.moment() 了(它现在是一个对象,不再有函数调用)。Webstorm 告诉我:"cannot invoke an expression whose type lacks a call signature. Type 'Moment' has no compatible call signatures."。

3) 我不能再使用 MomentStatic,因为它没有被导出。如果我键入 private moment: moment.MomentStatic,WebStorm 将会报告:"namespace 'moment' does not have an exported member 'MomentStatic'"。

因此,在这个例子中,我应该使用什么样的输入?


2
你的标题中提到了“ES6”,但从代码和标签来看,似乎你实际上使用的是TypeScript。你应该使用#2,并且会有一个全局的moment可以使用,例如getDate(): moment.Moment { return moment(); } - Heretic Monkey
查看 moment.d.ts。顺便说一下,moment 是一个命名空间,而不是一个类型。 - user663031
@torazaburo,没错。 moment 也是一个函数(declare function moment(): moment.Moment)。但我想知道如何为变量指定类型,以便可以在其上调用该函数?(moment在其接口上有一个名为()的函数,但我似乎无法为变量指定moment类型) - Mr.wiseguy
4
你正在寻找 moment.Moment - user663031
@torazaburo,使用它会导致WebStorm给出警告:“无法调用类型缺乏调用标记的表达式。类型'Moment'没有兼容的调用签名。”。所以我猜那不是它的问题:(如果我检查一下moment typings,接口“Moment”没有任何函数签名,如moment()(). - Mr.wiseguy
显示剩余3条评论
4个回答

96

正如Mike McCaughan所说,moment对象无法在构造函数中注入。不过,在旧版本的MomentJS中,这是可以实现的。通过移除构造函数属性并访问通过import * as moment from "moment"引入的全局moment对象,可以解决此问题。

moment()函数返回一个Moment对象。可以使用moment.Moment对其进行类型标注。

因此,代码可以重写为:

import * as moment from "moment";

export class DateThingy{

     constructor() {
     }

     public getDate(): moment.Moment { 
        return moment();
     }
}

30

你可以这样导入并使用moment类型:

import moment, { Moment } from "moment";

const timeNow: Moment = moment();

3
这应该是被接受的答案。为什么这个答案得票这么少? - Nelson Teixeira
1
我经常问自己这个问题,@NelsonTeixeira - fredrivett
@NelsonTeixeira 我同意。 - Jayant Joseph
只有在我的 Angular 项目的 tsconfig.json 文件的 compilerOptions 部分设置了 "allowSyntheticDefaultImports": true,才能正常工作。 - Jette

22

你尝试过不使用别名导入moment吗?

import moment from 'moment';

对我而言这种方法可行,而且typescript编译器也不会有问题。

const date = moment().format('YYYYMMDD');

请注意,这需要更新tsconfig!

在TSConfig中,您需要添加选项allowSyntheticDefaultImports以允许导入没有默认导出的库的默认导入。

示例(tsconfig.json):

{
  "compileOnSave": false,
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
  }
}

它说:moment没有默认的导出;即使它修复了下一个错误:error TS2349:Cannot invoke an expression whose type lacks a call signature. Type 'typeof moment' has no compatible call signatures. - Kunok
3
@Kunok,你需要在tsconfig.json中添加“allowSyntheticDefaultImports:true”(https://www.typescriptlang.org/docs/handbook/compiler-options.html),以便在TypeScript中能够以这种方式使用没有默认导出的库。 - Mr.wiseguy

-1

我收到了这样的错误信息:

无法调用其类型缺少调用签名的表达式。类型 "typeof moment" 没有兼容的调用签名。

我的问题是使用别名导入

import * as momentns from 'moment';

我将其更改为

import moment from 'moment';

对我来说解决了在 angular 8 (TypeScript 2.4) 中的问题。


重复的答案 - OHM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接