23

我正在尝试使用 typescript 中的 momentJs:根据我用来编译 typescript 的模块系统,我发现了关于如何使用 momentJs 的不同行为。使用commonJs编译 typescript 时,一切都按预期工作,我可以按照 momentJs 文档进行操作:

import moment = require("moment");
moment(new Date()); //this works

如果我在导入“时刻”时使用“系统”作为打字稿模块系统,我将被迫这样做

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;

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

4

8 回答 8

19

发生这种情况是因为 SystemJSmoment通过将其包装在模块对象中来自动转换为 ES6 样式的模块,而 CommonJS 不是。

CommonJS 引入moment,我们得到了实际的moment函数。这是我们在 JavaScript 中一直在做的事情,看起来应该很熟悉。就好像你写的:

var moment = function moment() {/*implementation*/}

SystemJS 引入moment,它不会为您提供 moment 功能。它创建一个对象,将矩函数分配给名为 的属性default。就好像你写的:

var moment = {
    default: function moment() {/*implementation*/}
}

为什么这样做?因为根据 ES6/TS,模块应该是一个或多个属性的映射,而不是函数。在 ES6 中,以前导出自身的大量外部库的约定是在default模块对象的属性下使用以下方式导出自身(在此处export default阅读更多信息;在 ES6/TypeScript 中,您可以使用紧凑语法导入这样的函数)。import moment from "moment"

您没有做错任何事情,您只需要选择导入模块的格式,并坚持您的选择。如果您想同时使用 CommonJS 和 SystemJS,您可能会考虑将它们配置为使用相同的导入样式。搜索“systemjs 默认导入”导致我讨论了您的问题,他们在其中实现了--allowSyntheticDefaultImports设置。

于 2015-12-08T23:28:32.240 回答
8

我通过更换解决了这个问题

import moment from "moment";

导入语句

import * as moment from "moment";

这。

于 2021-01-19T05:04:29.717 回答
5

我做了以下事情:

我安装moment 定义文件如下:

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 导出一个函数(即_moment = utils_hooks__hooksandutils_hooks__hooks是一个函数,这很清楚。

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

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

于 2015-12-03T14:25:00.793 回答
3

这是我对 System.js 和 Typescript 1.7.5 所做的

import * as moment from "moment";
...
moment.utc(); // outputs 2015 (for now).

但请注意,我使用的是utc()方法。我不能使用moment(),因为作为 mk。moment.default()已经解释了,这是由System.js转换成的。当然,绝对类型的类型不包含default方法,因此为了避免编译错误,需要使用类似moment["default"]()(我知道,丑陋的)之类的东西。

下一步,我需要将以下内容添加到 System.js 配置中:

System.config({
  paths: {
    'moment': 'node_modules/moment/moment.js'
  }
});

在此之后,一切都作为一个魅力。

于 2015-12-19T09:56:28.640 回答
2

进入我正在从事的项目的时刻是一种痛苦,但我们最终使用以下方法解决了它:

import momentRef = require('moment');
var moment: moment.MomentStatic = momentRef;
于 2015-10-07T11:50:00.990 回答
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';
于 2016-03-17T16:37:33.850 回答
0

我有

import * as moment from 'moment';

并改变了我认为应该是的一切

var date: moment = moment();

var date: moment.Moment = moment();

于 2016-05-19T22:29:06.683 回答
0

如果您使用的是 typescript,则默认导入 likeimport moment from "moment"的行为与const moment = require("moment").default. 见 https://www.typescriptlang.org/tsconfig#esModuleInterop

TLDR; 添加esModuleInterop: true你的 tsconfig.json

于 2021-09-27T11:59:30.263 回答