如何在TypeScript中使用带有SystemJS的momentjs?

时间:2015-11-26 12:19:11

标签: typescript momentjs systemjs

我的项目设置包括' jspm'图书馆工具和' tsd'打字工具。

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

  

在我的文件中(使用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);

我得到一个&#34; TypeError:时刻不是一个功能&#34;

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

有人可以帮忙吗?

8 个答案:

答案 0 :(得分:29)

我做了以下事情:

我安装了moment definition file,如下所示:

tsd install moment --save

然后我创建了 main.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资源库中提出一个问题,看看他们是否认为它是一个bug(或一个特性:)。

答案 1 :(得分:4)

由于代理限制我无法使用npm,因此无法使用npm,因此无法使用npm(因此必须手动安装库)。如果将时刻和绝对式文件的版本安装在项目的适当位置,您可以通过一些摆弄来实现这一点。

关于使用片刻配置打字稿有一个有用的注释here on the moment.js website 。在我的案例中帮助的关键方面是在我的tsconfig.json文件的compilerOptions部分添加以下内容:

"allowSyntheticDefaultImports": true

答案 2 :(得分:3)

这适用于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 *语法,并且在进行一些升级后我也不得不切换到它(不知道为什么)。

答案 3 :(得分:1)

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

import moment from 'moment';

它说无法找到模块&#39;时刻&#39;。我已经安装了作为npm包的时刻并且它正确引用但是由于这个原因,那个moment.d.ts导出的时刻作为命名空间而不是模块,如下所示,我无法引用它。

export = moment; 

所以如果我把它改成

declare module 'moment' {
    export default moment;
}

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

答案 4 :(得分:0)

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

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

enter image description here

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

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

我的项目构建正常,我在浏览器中看到了测试警报。

答案 5 :(得分:0)

刚刚完成了我的项目。这是有角度的,但我认为这不重要,可能会让你走上正确的道路。这很容易:

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
  }

  ...

答案 6 :(得分:0)

我假设片刻是使用

安装的
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.default导入。 像

这样的东西
moment.default().format('dddd, MMMM Do YYYY, h:mm:ss a')

实际上可能在您的代码中起作用,但不是打算使用的方式。

答案 7 :(得分:0)

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