如何使用Typescript导入moment.js?


93

我正在尝试学习打字稿。虽然我认为这无关紧要,但我正在使用VSCode进行此演示。

我有一个package.json包含这些部分的内容:

{
  "devDependencies": {
    "gulp": "^3.9.1",
    "jspm": "^0.16.33",
    "typescript": "^1.8.10"
  },
  "jspm": {
    "moment": "npm:moment@^2.12.0"
  }
}

然后我有一个main.js像这样的Typescript类:

import moment from 'moment';
export class Main {
}

我的gulpfile.js样子是这样的:

var gulp = require('gulp');
var typescript = require('gulp-tsb');
var compilerOptions = {
                        "rootDir": "src/",
                        "sourceMap": true,
                        "target": "es5",
                        "module": "amd",
                        "declaration": false,
                        "noImplicitAny": false,
                        "noResolve": true,
                        "removeComments": true,
                        "noLib": false,
                        "emitDecoratorMetadata": true,
                        "experimentalDecorators": true
                      };
var typescriptCompiler = typescript.create(compilerOptions);
gulp.task('build', function() {
  return gulp.src('/src')
    .pipe(typescriptCompiler())
    .pipe(gulp.dest('/dest'));
});

当我运行gulp build时,出现以下消息: "../main.ts(1,25): Cannot file module 'moment'."

如果使用,import moment = require('moment');则jspm将可以运行并在运行应用程序时引入模块,但仍收到构建错误。我也尝试过:

npm install typings -g
typings install moment --ambient --save

但是,并没有使问题变得更好,反而变得更糟。现在,我在构建时收到上述错误以及以下内容:"../typings/browser/ambient/moment/index.d.ts(9,21): Cannot find namespace 'moment'."

如果我进入通过键入提供的文件,并在文件底部添加:

declare module "moment" { export = moment; }

我可以得到第二个错误,但是我仍然需要require语句以花些时间在main.ts文件中工作,并且仍然遇到第一个构建错误。

我是否需要.d.ts暂时创建自己的文件,或者只是缺少一些设置文件?


添加此更新谁现在运行到这个人:import moment, { Moment } from 'moment';让你做const x = moment();const x: Moment = moment();
ryuu9187

这些解决方案均无效
chrismarx

Answers:


119

更新资料

显然,moment现在提供了自己的类型定义(根据sivabudh至少从2.14.1开始),因此您根本不需要typings或根本不需要@types

import * as moment from 'moment' 应该加载npm软件包提供的类型定义。

话虽这么说,如moment / pull / 3319#issuecomment-263752265中所述,目前团队在维护这些定义时似乎存在一些问题(他们仍在寻找维护它们的人)


您需要安装moment没有--ambient标志的类型。

然后使用 import * as moment from 'moment'


那行得通。您能解释一下使用--ambient标志与不使用标志之间的区别吗?我让numericjs使用环境标志工作。另外,他们的主页npmjs.com/package/typings给出了使用环境标志的示例。我不知道何时/何时需要使用另一个。谢谢!
peinearydevelopment '16

1
老实说,我不能。通常,您--ambienttypings/中的所有Typescript定义都使用该标志,DefinitelyTyped但是该moment定义具有一些奇怪的结构,并且文件下载不正确。如果查看定义文件moment.d.ts,则该文件仅包含对节点版本的引用,下载时无法解决该问题(可能值得提出一个问题)。
助手

显然已经有一个与此问题相关的信息:github.com/DefinitelyTyped/DefinitelyTyped/issues/8388
peinearydevelopment

1
我从'moment / moment'b / c开始使用import *来工作,它作为子文件夹安装在node-modules文件夹中。
user441058'7

1
我使用的是webpack,当前版本为2.17.1,但仍然无法正常运行。我尝试过:从*时刻开始导入*;并从“时刻/时刻”中导入*作为时刻;而且不行!
Mohy Eldeen

58

您需要在TS中分别导入moment()函数和Moment类。

我在这里的打字稿文档中找到了一个注释。

/ *〜请注意,ES6模块不能直接导出可调用函数
*〜此文件应使用CommonJS样式
导入:*〜import x = require('someLibrary');

因此,将moment js导入打字稿的代码实际上如下所示:

import { Moment } from 'moment'
....
let moment = require('moment');
...
interface SomeTime {
  aMoment: Moment,
}
...
fn() {
  ...
  someTime.aMoment = moment(...);
  ...
}

1
好的答案,因为它表明类型和功能之间的差异。谢谢!
Jelle

找不到名称“ require”
编码容器

4
现在,可以将其用作import * as moment from 'moment';,然后moment.Moment用于键入。
流星

对我有用的是:导入时间= require('moment');
Telmo Pimentel Mota

实际上,您也可以moment.Moment直接从名称空间使用接口moment
HalfWebDev,

19

不确定何时更改,但是使用最新版本的打字稿,您只需要使用它import moment from 'moment';,其他所有内容就可以正常使用。

更新:

看起来好像最近固定了它们的导入。至少2.24.0您要使用import * as moment from 'moment';


5
import * as moment from 'moment'不能与打字稿一起使用,但是import moment from 'moment'可以。
斯图尔特·麦金太尔'18

它正在工作,但是我正在获取格林尼治标准时间0,但我需要的是当地时间,该时间不起作用,我也尝试使用moment()。utc()。format(),但它会重现相同的结果。
kbhaskar '19

@kbhaskar修复了导入的最新版本。查看最新答案
NSjonas

1
我认为这差不多。我唯一要做的额外步骤是在我的配置中添加esModuleInteropset true,这是我从此答案中获得的。谢谢。
Mark Birbeck

14

通过打字

Moment.js现在在v2.14.1中支持TypeScript。

参见:https : //github.com/moment/moment/pull/3280


可能不是最佳答案,但这是蛮力的方式,对我有用。

  1. 只需下载实际moment.js文件并将其包含在您的项目中即可。
  2. 例如,我的项目如下所示:

$ tree . ├── main.js ├── main.js.map ├── main.ts └── moment.js

  1. 这是一个示例源代码:

```

import * as moment from 'moment';

class HelloWorld {
    public hello(input:string):string {
        if (input === '') {
            return "Hello, World!";
        }
        else {
            return "Hello, " + input + "!";
        }
    }
}

let h = new HelloWorld();
console.log(moment().format('YYYY-MM-DD HH:mm:ss'));
  1. 只需使用node即可运行main.js

是的,我确认这是最正确的答案。像魅力一样工作。
Capy

当我尝试使用npm i @ types / moment执行此操作时,收到错误消息:TypeScript错误:src \ app.ts(1,1):错误TS7038:无法调用或构造名称空间样式的导入,这将导致运行时失败。在tsc -v 2.7.2
GONeale '18

1

我刚刚注意到,我投票并评论的答案是模棱两可的。因此,以下正是对我有用的方法。我目前在Moment 2.26.0和TS上3.8.3

在代码中:

import moment from 'moment';

在TS配置中:

{
  "compilerOptions": {
    "esModuleInterop": true,
    ...
  }
}

我建立了所以这个配置导入到其他配置文件CommonJS的和EMS。

洞察力来自于与使用Express有关的答案。我觉得值得在这里添加,以帮助任何与Moment.js相关的人,而不是更一般的人。


那么你可以使用moment()像正常的,而不是moment.default()
xinthose


0

还是坏了?尝试卸载@types/moment

因此,我@types/momentpackage.json文件中删除了程序包,并使用了以下命令:

import * as moment from 'moment'

较新版本的moment不需要@types/moment软件包,因为类型已经包含在内。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.