【问题标题】:How to use momentjs in TypeScript with SystemJS?如何在带有 SystemJS 的 TypeScript 中使用 momentjs?
【发布时间】:2015-11-26 12:19:11
【问题描述】:

我的项目设置包括用于库的“jspm”工具和用于打字的“tsd”工具。

安装 moment 的 TypeScript d.ts 文件 (these) 后,我找不到加载和实际使用 moment 实例的方法。

在我的文件中(使用 SystemJS 模块加载)

/// <reference path="../../../typings/tsd.d.ts" />
import * as moment from "moment";
import * as _ from "lodash";
...
...
const now = (this.timestamp === 0) ? moment() : moment(this.timestamp);

我收到“TypeError: moment is not a function

定义的结构与lodash相同,效果很好,所以我不知道可能是什么原因。

谁能帮忙?

【问题讨论】:

  • 你试过import { moment } from 'moment'吗?如果找不到较新版本的 d.ts,尝试使用 moment 2.8.0 也可能很有用。
  • @wilenx 真有趣,我刚刚在大约 10 分钟前为这个问题添加了赏金stackoverflow.com/questions/32987273/…

标签: typescript momentjs systemjs


【解决方案1】:

我做了以下事情:

我安装momentdefinition file如下:

tsd install moment --save

然后我创建了 ma​​in.ts

///<reference path="typings/moment/moment.d.ts" />

import moment = require("moment");
moment(new Date());

然后我跑了:

$ tsc --module system --target es5 main.ts # no error 
$ tsc --module commonjs --target es5 main.ts # no error 

main.js 看起来像这样:

// https://github.com/ModuleLoader/es6-module-loader/blob/v0.17.0/docs/system-register.md - this is the corresponding doc
///<reference path="typings/moment/moment.d.ts" />
System.register(["moment"], function(exports_1) {
    var moment;
    return {
        setters:[
            function (moment_1) {
                // You can place `debugger;` command to debug the issue
                // "PLACE XY"
                moment = moment_1;
            }],
        execute: function() {
            moment(new Date());
        }
    }
});

我的 TypeScript 版本是 1.6.2。

这是我发现的:

Momentjs 导出一个function(即_moment = utils_hooks__hooksutils_hooks__hooks 是一个函数,这很清楚。

如果你在上面我标记为PLACE XY 的地方放置一个断点,你可以看到moment_1 是一个对象(!)而不是一个函数。相关线路:12

总而言之,问题与 TypeScript 无关。问题是 systemjs 不保留 momentjs 导出函数的信息。 Systemjs 只是从模块中复制导出对象的属性(函数也是 JavaScript 中的对象)。我想你应该在 systemjs 存储库中提交一个问题,看看他们是否认为这是一个错误(或一个特性:))。

【讨论】:

  • 导入需要是这样的:import * as moment from "moment";
  • 现在你应该使用npm install @types/moment --save 而不是tsd install moment --save 并将typeRoots 添加到你的tsconfig.json"typeRoots": [ "../node_modules/@types" ]
  • @Highmastdon @types/moment@2.13.0: This is a stub types definition for Moment (https://github.com/moment/moment). Moment provides its own type definitions, so you don't need @types/moment installed!
【解决方案2】:

从 2.13 版开始,moment 包括 Typescript 打字。不再需要使用tsd(或typings)。

systemjs.config.js 文件中,只需添加以下内容:

  var map = {
    // (...)
    moment: 'node_modules/moment',      
  };

  var packages = {
    // (...)
    moment: { main: 'moment.js', defaultExtension: 'js' },
  };

在模块中:

import moment = require('moment')

【讨论】:

  • 一个小修正我正在使用 moment 2.15,我只能使用 import * as moment from 'moment' 导入它;如果我使用你提到的方式,我会得到一个 TS 错误 moment has no default export
  • 很奇怪。你确定你使用的是随 moment 包分发的类型吗?如果你使用import moment = require('moment') 会怎样?
  • 嘿,是的,那是使用最新时刻的分布式类型定义,使用 typescript 2.0,import moment = require('moment') 似乎工作正常,意味着编译和运行正常,但 intellij 不会自动完成正确地使用时刻方法,就像使用 import * as moment from 'moment';
  • import * as moment from 'moment'; 的问题是方法应该可以正常运行,但我不认为像 new moment() 这样的东西可以正常工作。 IntelliJ 不使用 require 语法可能是 intelliJ 的问题(它适用于 Atom Typescript 模块)
  • 我会编辑我的答案,因为import moment = require('moment') 是正确的做法
【解决方案3】:

由于代理限制,我无法使用 npm(因此必须手动安装库),所以我很难让它工作。如果将 moment 和 absolutetyped 文件的版本安装在项目中的适当位置,您可以稍微摆弄一下。

有一个有用的注释here on the moment.js website 关于使用 moment 配置 typescript。对我来说有帮助的关键方面是在我的 tsconfig.json 文件的 compilerOptions 部分添加以下内容:

"allowSyntheticDefaultImports": true

【讨论】:

  • 这是这个页面上唯一一个对我使用 TypeScript 的项目,这里有一些额外的背景来获得时间工作的过程:github.com/moment/moment/issues/2608 - 特别是 5 月 23 日 gfviegas 的评论, 2016。在此设置之后,我只需要使用 import * as moment from 'moment' 然后 moment().format 按预期工作。
【解决方案4】:

这适用于 Angular 2,但不应该特定于它。你基本上只是告诉系统加载器在哪里可以找到moment.min.js

system.config.js:

// map tells the System loader where to look for things
var map = {
  'app':                        'app', // 'dist',

  '@angular':                   'node_modules/@angular',
  'rxjs':                       'node_modules/rxjs',

  // tell system where to look for moment
  'moment':                     'node_modules/moment/min'
};

// packages tells the System loader how to load when no filename and/or no extension
var packages = {
  'app':                        { main: 'main.js',  defaultExtension: 'js' },
  'rxjs':                       { defaultExtension: 'js' },

  // tell system which file represents the script when you import
  'moment':                     { main: 'moment.min.js', defaultExtension: 'js'}
};

在您的模块中:

import moment from 'moment';

或(2016 年 10 月 13 日编辑):

import * as moment from 'moment';

一些评论者在上面发布了import * 语法,我在一些升级后也不得不切换到它(不知道为什么)。

【讨论】:

  • 我不得不使用 'import * as moment from 'moment';'在我的 TS 文件中加载时刻。
【解决方案5】:

在我的打字稿文件中,当我使用

import moment from 'moment';

它说找不到模块'moment'。我已经将 moment 安装为 npm 包并且它被正确引用但由于原因,moment.d.ts 将时刻导出为命名空间而不是模块,如下所示,我无法引用它。

export = moment; 

所以如果我把它改成

declare module 'moment' {
    export default moment;
}

导入完美。我在这里做错了什么?

【讨论】:

  • 嗨,阿里,欢迎来到 Stack Overflow!不幸的是,您发布了您的问题作为对其他人问题的回答。相反,我建议您自己提出一个新问题,并让社区以这种方式帮助您。祝你好运!
【解决方案6】:

如果您尝试将 moment 用于客户端开发还是用于服务器端(例如 node.js),这有点不清楚。但是,如果您的案例是前端,那么我可以很轻松地使用时刻:

1) 我刚刚将文件添加到我的项目中:

2) 写了一个简单的测试代码:

window.onload = () =>
{
    var timestamp: number = 111111111111111;
    var momentResult: moment.Moment = moment(timestamp);
    alert(momentResult.toISOString());
};

我的项目构建成功,我在浏览器中看到了一个测试警报。

【讨论】:

  • 我的设置包括用于库的“jspm”和用于打字的“tsd”cli,没有像您使用的直接脚本标签。我将编辑问题以澄清。不过感谢您的努力!
【解决方案7】:

刚刚在我的项目中完成。它是有角度的,但我认为这并不重要,可能会让你走上正确的道路。很简单:

import MomentStatic = moment.MomentStatic;

class HelpdeskTicketController {
  constructor(private moment: MomentStatic) { // angulars dependency injection, you will have some global probably
    let d = this.moment(new Date()); // works
    console.log(d.add(2, 'hours').format()); // works
  }

  ...

【讨论】:

    【解决方案8】:

    我假设 moment 是使用安装的

    jspm install moment
    

    这应该在您的 config.js 的地图部分添加一个条目。

    ...
    "moment": "npm:moment@2.10.6",
    ...
    

    这样你可以通过

    访问你的js文件中的时刻
    import moment from 'moment';
    
    console.log(moment().format('dddd, MMMM Do YYYY, h:mm:ss a'));
    

    当您导入 * as moment 时,您将导入模块命名空间。所以 moment 将是一个对象,其属性是模块导出。这样,默认导出不会作为时刻导入,而是作为 moment.default 导入。 所以像

    moment.default().format('dddd, MMMM Do YYYY, h:mm:ss a')
    

    实际上可能在您的代码中工作,但不是它的预期使用方式。

    【讨论】:

    • 感谢您的回答。写“从“时刻”导入时刻;”导致“模块'moment'没有默认导出”类型的错误(这是真的)
    • 你使用哪个版本的momentjs?我认为已经进行了一些相关的讨论。见github.com/moment/moment/issues/2576 & github.com/moment/moment/pull/2577
    • 2.10.6 和 2.8.0 的类型。我觉得很奇怪,我找不到将它集成到我的打字稿中的方法,没有做任何特别的事情,而且现在成为一个如此受欢迎的图书馆...... :(
    • 没关系。尽管如此,我还是很感激。
    • 尝试: import { moment } from 'moment';如果找不到较新版本的 d.ts,尝试使用 moment 2.8.0 也可能很有用。
    【解决方案9】:

    对于我的东西,我将 Webpack 与 VS 2015(更新 3)一起使用。因此,在为 package.json 和 webpack.config.vendor.js 文件添加代码之后,我只需要在我的组件(TypeScript,Angular 2)的最顶部调用 import moment = require('moment')。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-17
      • 2016-07-29
      • 2016-08-01
      • 2023-03-30
      • 1970-01-01
      相关资源
      最近更新 更多