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.
