如何在带有 SystemJS 的 TypeScript 中使用 momentjs?
How to use momentjs in TypeScript with SystemJS?
我的项目设置包括 'jspm' 库工具和 'tsd' 打字工具。
安装 moment 的 TypeScript d.ts 文件(these)后,我找不到加载和实际使用 moment 实例的方法。
In my file (using SystemJS module loading)
/// <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 不是函数”
定义的结构与 lodash 相同,工作正常,所以我不知道可能是什么原因。
有人能帮忙吗?
有点不清楚你是想把moment用于客户端开发还是服务器端(例如node.js)。但是,如果你的情况是前端,那么我可以很轻松地使用 moment:
1) 我刚刚将文件添加到我的项目中:
2) 写了一个简单的测试代码:
window.onload = () =>
{
var timestamp: number = 111111111111111;
var momentResult: moment.Moment = moment(timestamp);
alert(momentResult.toISOString());
};
我的项目构建正常,我在浏览器中看到了测试警报。
刚刚在我的项目中完成。它是 angular,但我认为这并不重要,可能会让您走上正确的道路。很简单:
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
}
...
我假设 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
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__hooks
和utils_hooks__hooks
是一个函数,很清楚。
如果你在我上面标为PLACE XY
的地方下一个断点,你可以看到moment_1
是一个对象(!)而不是一个函数。相关行:1, 2
综上所述,问题与TypeScript无关。问题是 systemjs 不保留 momentjs 导出函数的信息。 Systemjs 只是从模块中复制导出对象的属性(函数也是 JavaScript 中的对象)。我想你应该在 systemjs 存储库中提交一个问题,看看他们是否认为它是一个错误(或一个功能 :))。
这适用于 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 *
语法,我在升级后也不得不切换到那个语法(不知道为什么)。
从 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')
在我的打字稿文件中,当我使用
import moment from 'moment';
它说找不到模块 'moment'。我已经将 moment 安装为 npm 包并且它被正确引用但是由于 moment.d.ts 将 moment 导出为命名空间而不是模块,如下所示,我无法引用它。
export = moment;
所以如果我把它改成
declare module 'moment' {
export default moment;
}
导入工作完美。我在这里做错了什么?
我很难让它工作,因为由于代理限制我无法使用 npm(因此不得不手动安装库)。如果将 moment 和 definitelytyped 文件的版本安装在项目中的适当位置,您可以通过一些摆弄来使它工作。
关于使用 moment 配置打字稿,有一个有用的说明 here on the moment.js website 。对我的案例有帮助的关键方面是在我的 tsconfig.json 文件的 compilerOptions 部分添加以下内容:
"allowSyntheticDefaultImports": true
对于我的东西,我将 Webpack 与 VS 2015(更新 3)一起使用。因此,在为 package.json 和 webpack.config.vendor.js 文件添加代码后,我只需要在组件的最顶部调用 import moment = require('moment') (TypeScript,Angular 2).
我的项目设置包括 'jspm' 库工具和 'tsd' 打字工具。
安装 moment 的 TypeScript d.ts 文件(these)后,我找不到加载和实际使用 moment 实例的方法。
In my file (using SystemJS module loading)
/// <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 不是函数”
定义的结构与 lodash 相同,工作正常,所以我不知道可能是什么原因。
有人能帮忙吗?
有点不清楚你是想把moment用于客户端开发还是服务器端(例如node.js)。但是,如果你的情况是前端,那么我可以很轻松地使用 moment:
1) 我刚刚将文件添加到我的项目中:
2) 写了一个简单的测试代码:
window.onload = () =>
{
var timestamp: number = 111111111111111;
var momentResult: moment.Moment = moment(timestamp);
alert(momentResult.toISOString());
};
我的项目构建正常,我在浏览器中看到了测试警报。
刚刚在我的项目中完成。它是 angular,但我认为这并不重要,可能会让您走上正确的道路。很简单:
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
}
...
我假设 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
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__hooks
和utils_hooks__hooks
是一个函数,很清楚。
如果你在我上面标为PLACE XY
的地方下一个断点,你可以看到moment_1
是一个对象(!)而不是一个函数。相关行:1, 2
综上所述,问题与TypeScript无关。问题是 systemjs 不保留 momentjs 导出函数的信息。 Systemjs 只是从模块中复制导出对象的属性(函数也是 JavaScript 中的对象)。我想你应该在 systemjs 存储库中提交一个问题,看看他们是否认为它是一个错误(或一个功能 :))。
这适用于 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 *
语法,我在升级后也不得不切换到那个语法(不知道为什么)。
从 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')
在我的打字稿文件中,当我使用
import moment from 'moment';
它说找不到模块 'moment'。我已经将 moment 安装为 npm 包并且它被正确引用但是由于 moment.d.ts 将 moment 导出为命名空间而不是模块,如下所示,我无法引用它。
export = moment;
所以如果我把它改成
declare module 'moment' {
export default moment;
}
导入工作完美。我在这里做错了什么?
我很难让它工作,因为由于代理限制我无法使用 npm(因此不得不手动安装库)。如果将 moment 和 definitelytyped 文件的版本安装在项目中的适当位置,您可以通过一些摆弄来使它工作。
关于使用 moment 配置打字稿,有一个有用的说明 here on the moment.js website 。对我的案例有帮助的关键方面是在我的 tsconfig.json 文件的 compilerOptions 部分添加以下内容:
"allowSyntheticDefaultImports": true
对于我的东西,我将 Webpack 与 VS 2015(更新 3)一起使用。因此,在为 package.json 和 webpack.config.vendor.js 文件添加代码后,我只需要在组件的最顶部调用 import moment = require('moment') (TypeScript,Angular 2).