23

typescript から momentJs を使用しようとしています: typescript のコンパイルに使用しているモジュール システムに応じて、momentJs の使用方法について異なる動作を見つけます。typescript をcommonJsでコンパイルすると、すべてが期待どおりに機能し、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

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

CommonJSがを取り込むmomentと、実際のmoment関数が得られます。これは、しばらくの間 JavaScript で行ってきたことであり、非常に見慣れているはずです。それはあなたが書いたかのようです:

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

SystemJSが を取り込むmomentと、モーメント機能が提供されません。という名前のプロパティにモーメント関数が割り当てられたオブジェクトを作成しますdefault。それはあなたが書いたかのようです:

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

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

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

于 2015-12-08T23:28:32.240 に答える
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__hooksutils_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 に答える
0

私が持っていた

import * as moment from 'moment';

私がそうあるべきだと思っていたすべてを変えた

var date: moment = moment();

var date: moment.Moment = moment();

于 2016-05-19T22:29:06.683 に答える
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 に答える