TypeScript-modulsystem på momentJS beter sig konstigt


Jag försöker använda momentJs från TypeScript: beroende på vilken modulsystem jag använder för att kompilera TypeScript, märker jag ett annat beteende på hur jag kan använda momentJs. När jag kompilerar TypeScript med commonJs fungerar allt som förväntat och jag kan bara följa momentJs dokumentation:

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

Om jag använder "system" som TypeScript-modulsystem när jag importerar "moment" tvingas jag göra

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

Jag hittade en lösning för att få dem båda att fungera oavsett vilken TypeScript-modulsystem som används

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

Jag gillar inte detta, och jag skulle vilja förstå varför det beter sig så här. Gör jag något fel? Kan någon förklara för mig vad som händer?

Svar #1

Jag löste problemet genom att ersätta

import moment from "moment";

import-uttryck med

import * as moment from "moment";

det här.

Svar #2

Detta händer eftersom SystemJS automatiskt omvandlar moment till en ES6-stil modul genom att kapsla in den i ett modulobjekt, medan CommonJS inte gör det.

När CommonJS hämtar moment, får vi den faktiska moment-funktionen. Detta är vad vi har gjort i JavaScript ett tag nu, och det borde se väldigt bekant ut. Det är som om du skrev:

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

När SystemJS hämtar moment, ger det dig inte moment-funktionen. Det skapar ett objekt med moment-funktionen tilldelad en egenskap som heter default. Det är som om du skrev:

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

Varför gör det så? Eftersom en modul enligt ES6/TS bör vara en karta över en eller flera egenskaper, inte en funktion. I ES6 är konventionen för stora externa bibliotek som tidigare exporterade sig själva att exportera sig själva under default-egenskapen av ett modulobjekt med export default (läs mer här; i ES6/TypeScript kan du importera funktioner på detta sätt med den kompakta import moment from "moment"-syntaksen).

Du gör inget fel, du behöver bara välja formatet på dina importerade moduler och hålla dig till ditt val. Om du vill använda både CommonJS och SystemJS kan du kanske se över att konfigurera dem så att de använder samma importstil. En sökning efter 'systemjs default import' ledde mig till denna diskussion om ditt problem, där de implementerar inställningen --allowSyntheticDefaultImports.

Relaterade artiklar