我试图从打字稿中使用momentJs: 根据我用来编写打字稿的模块系统,我发现了一个关于如何使用momentJs的不同行为。 使用 commonJs 编译typescript时,一切都按预期工作,我可以关注momentJs文档:
import moment = require("moment");
moment(new Date()); //this works
如果我在导入"时刻"时使用" system" 作为打字稿模块系统我被迫做了
import moment = require("moment");
moment.default(new Date()); //this works
moment(new Date()); //this doesn't work
我发现了一种解决方法,无论使用的打字稿模块系统如何,它们都能正常工作
import m = require("moment")
var moment : moment.MomentStatic;
moment = (m as any).default || m;
我不喜欢这样,我想理解为什么它会像这样。难道我做错了什么?谁能解释一下我发生了什么?
答案 0 :(得分:15)
这是因为SystemJS通过将moment
包装到模块对象中而自动将moment
转换为ES6样式的模块,而CommonJS则不会。
当 CommonJS 拉入moment
时,我们会获得实际的var moment = function moment() {/*implementation*/}
功能。这就是我们在JavaScript中已经做了一段时间了,它应该看起来非常熟悉。就像你写的那样:
moment
当 SystemJS 拉入default
时,它不会为您提供时刻功能。它创建一个对象,其时刻函数分配给名为var moment = {
default: function moment() {/*implementation*/}
}
的属性。就像你写的那样:
default
为什么这样做?因为根据ES6 / TS,模块应该是一个或多个属性的映射,而不是函数。在ES6中,以前导出自身的大规模外部库的约定是使用export default
在模块对象的import moment from "moment"
属性下导出自己(更多here;在ES6 / TypeScript中,你可以使用紧凑的--allowSyntheticDefaultImports
语法导入这样的函数。
你没有做错任何事,你只需要选择导入模块的格式,并坚持你的选择。如果要同时使用CommonJS和SystemJS,可以考虑将它们配置为使用相同的导入样式。搜索“systemjs默认导入”会导致我发现您问题的this discussion,并在其中实施'use strict';
var userData; //// important variable store all data
var React = require('react-native');
var PRList = require('./prlist.js');
var {
AppRegistry,
StyleSheet,
Text,
View,
....
} = React;
var firstapp003 = React.createClass({
_renderScene(route,navigator){
if(route.id===1){
return <Firstapp002 navigator={navigator} />
} else if(route.id===2){
return <Firstapp004 navigator={navigator} />
} else if(route.id===22){
return <PRList navigator={navigator} />
}
},
_configureScene(route){
return CustomSceneConfig;
},
render() {
return (
.....
);
}
});
var styles = StyleSheet.create({
....
});
AppRegistry.registerComponent('firstapp003', () => firstapp003);
设置。
答案 1 :(得分:5)
我做了以下事情:
我安装了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
TL; DR:最后,问题与TypeScript无关。问题是systemjs不保留momentjs导出函数的信息。 Systemjs只是从模块中复制导出对象的属性(函数也是JavaScript中的对象)。我想你应该在systemjs资源库中提出一个问题,看看他们是否认为它是一个bug(或一个特性:)。
答案 2 :(得分:4)
我通过替换解决了这个问题
import moment from "moment";
导入语句
import * as moment from "moment";
这个。
答案 3 :(得分:2)
对于我正在进行的项目来说,时刻是一种痛苦,但我们最终用这个来解决它:
import momentRef = require('moment');
var moment: moment.MomentStatic = momentRef;
答案 4 :(得分:2)
以下是我对System.js和Typescript 1.7.5
的处理方式import * as moment from "moment";
...
moment.utc(); // outputs 2015 (for now).
但请注意我使用utc()
方法。我不能使用moment()
因为mk。已经解释过,这由System.js转换为moment.default()
。原因绝对类型的打字不包含default
方法,所以为避免编译错误,需要使用像moment["default"]()
这样的东西(我知道,丑陋)。
下一步,我需要将以下内容添加到System.js配置中:
System.config({
paths: {
'moment': 'node_modules/moment/moment.js'
}
});
在此之后,所有人都充满了魅力。
答案 5 :(得分:0)
对于我的system.config:
paths: {
'moment': 'node_modules/moment/moment.js'
},
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
在我的组件中导入momentjs我删除了*我认为将moment.js文件中的代码视为多个对象。
变化:
import * as moment from 'moment';
为:
import moment from 'moment';
答案 6 :(得分:0)
我有
import * as moment from 'moment';
并改变了我认为应该是的所有内容
var date: moment = moment();
到
var date: moment.Moment = moment();