TypeScriptin moduulijärjestelmät momentJS:ssä käyttäytyvät oudosti


Yritän käyttää momentJs:ää Typescriptistä: riippuen siitä, mitä moduulijärjestelmää käytän Typescriptin kääntämiseen, huomaan erilaisen käyttäytymisen siinä, miten voin käyttää momentJs:ää. Kun käännän Typescriptin commonJs -järjestelmällä, kaikki toimii odotetusti ja voin yksinkertaisesti seurata momentJs:n dokumentaatiota:

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

Jos käytän "system" TypeScript-moduulijärjestelmänä, kun tuon "moment", olen pakotettu tekemään

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

Löysin kiertotien saadakseni ne molemmat toimimaan riippumatta käytetystä TypeScriptin moduulijärjestelmästä

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

En pidä tästä, ja haluaisin ymmärtää, miksi se käyttäytyy näin. Teenkö jotain väärin? Voiko joku selittää minulle, mitä tapahtuu?

Vastaus #1

Ratkaisin ongelman korvaamalla

import moment from "moment";

import-lauseella

import * as moment from "moment";

tämä.

Vastaus #2

Tämä tapahtuu, koska SystemJS muuntaa automaattisesti moment-kirjaston ES6-tyyliseksi moduuliksi käärelemällä sen moduuliobjektiin, kun taas CommonJS ei tee näin.

Kun CommonJS tuo moment-kirjaston, saamme varsinaisen moment-funktion. Tätä olemme tehneet JavaScriptissä jo jonkin aikaa, ja sen pitäisi näyttää hyvin tutulta. Se on kuin olisit kirjoittanut:

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

Kun SystemJS tuo moment-kirjaston, se ei anna sinulle moment-funktiota suoraan. Se luo objektin, johon moment-funktio on määritelty ominaisuuteen nimeltä default. Se on ikään kuin olisit kirjoittanut:

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

Miksi se tekee niin? Koska ES6/TS:n mukaan moduulin tulisi olla yhden tai useamman ominaisuuden kartta, ei funktio. ES6:ssa suuren ulkoisen kirjaston, joka aiemmin nimesi itsensä, käytäntönä on viedä se moduuliobjektin default-ominaisuuden kautta käyttäen export default (lue lisää tästä; ES6/TypeScriptissä voit tuoda funktioita näin käyttämällä tiivistä import moment from "moment"-syntaksia).

Et ole tekemässä mitään väärää, sinun tarvitsee vain valita tuomiesi moduulien formaatti ja pysyä valinnassasi. Jos haluat käyttää sekä CommonJS- että SystemJS-moduuleja, voit harkita niiden konfigurointia käyttämään samaa tuontityyliä. Haku 'systemjs default import' johti minut tähän keskusteluun ongelmastasi, jossa he toteuttavat --allowSyntheticDefaultImports-asetuksen.

Aiheeseen liittyviä artikkeleita