momentJS上的打字稿模块系统行为奇怪

时间:2015-10-07 08:24:23

标签: typescript momentjs commonjs systemjs

我试图从打字稿中使用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;

我不喜欢这样,我想理解为什么它会像这样。难道我做错了什么?谁能解释一下我发生了什么?

7 个答案:

答案 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__hooksutils_hooks__hooks是一个函数,非常清楚。

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

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();