web-dev-qa-db-ja.com

奇妙な振る舞いをするmomentJSのTypescriptモジュールシステム

TypeScriptからmomentJsを使用しようとしています。TypeScriptのコンパイルに使用しているモジュールシステムに応じて、momentJsの使用方法に異なる動作が見られます。 TypeScriptをcommonJsでコンパイルすると、すべてが期待どおりに機能し、momentJsのドキュメントに従うことができます。

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

"moment"をインポートするときにTypeScriptモジュールシステムとして"system"を使用すると、強制的に実行されます

import moment = require("moment");
moment.default(new Date()); //this works
moment(new Date()); //this doesn't work

使用するTypeScriptモジュールシステムに関係なく、両方を機能させるための回避策を見つけました

import m = require("moment")
var moment : moment.MomentStatic;
moment = (m as any).default || m;

私はこれが好きではありません、そしてなぜそれがこのように振る舞うのか理解したいと思います。私は何か間違ったことをしていますか?誰かが私に何が起こっているのか説明できますか?

20
nemenos

これは、SystemJSがmomentをモジュールオブジェクトでラップすることによってES6スタイルのモジュールに自動的に変換しているのに対し、CommonJSはそうではないために発生しています。

CommonJSmomentをプルすると、実際のmoment関数が得られます。これは私たちがJavaScriptでしばらく行ってきたことであり、非常に見覚えがあるはずです。それはあなたが書いたかのようです:

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

SystemJSmomentをプルする場合、モーメント関数は提供されません。 defaultという名前のプロパティに割り当てられたモーメント関数を使用してオブジェクトを作成します。それはあなたが書いたかのようです:

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

なぜそれをするのですか? ES6/TSによると、モジュールは関数ではなく1つ以上のプロパティのマップである必要があるためです。 ES6では、以前は自分自身をエクスポートしていた大規模な外部ライブラリの規則は、export defaultを使用してモジュールオブジェクトのdefaultプロパティの下で自分自身をエクスポートすることです(ES6では続きを読む ここ ;/TypeScriptでは、コンパクトなimport moment from "moment"構文を使用してこのような関数をインポートできます。

何も悪いことはしていません。インポートしたモジュールの形式を選択し、選択に固執する必要があります。 CommonJSとSystemJSの両方を使用する場合は、同じインポートスタイルを使用するように構成することを検討してください。 'systemjs default import'を検索すると、問題の このディスカッション になり、--allowSyntheticDefaultImports設定が実装されます。

15
mk.

これが私がSystem.jsとTypeScript1.7.5で行った方法です

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

ただし、utc()メソッドを使用していることに注意してください。 mkとしてmoment()を使用できません。説明しましたが、これはSystem.jsによってmoment.default()に変換されます。原因として、DefinitelyTyped型にはdefaultメソッドが含まれていないため、コンパイルエラーを回避するには、moment["default"]()のようなものを使用する必要があります(私は知っています、醜いです)。

次のステップでは、System.js構成に以下を追加する必要がありました。

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

この後、すべてが魅力として機能しました。

2
Kirill G.

私が取り組んでいるプロジェクトに引き込む瞬間は苦痛でしたが、私たちはこれを使用してそれを解決することになりました:

import momentRef = require('moment');
var moment: moment.MomentStatic = momentRef;
2
Brocco

私の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';
0
Randy Collier