Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript module systems on momentJS behaving strangely

Tags:

I'm trying to use momentJs from typescript: depending on what module system I'm using to compile typescript, I find a different behaviour on how I can use momentJs. When compiling typescript with commonJs everything works as expected and I can just follow momentJs documentation:

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

If I use "system" as typescript module system when I import "moment" I am forced to do

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

I found a workaround to make them both work regardless of typescript module system used

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

I don't like this, and I would like to understand why it behaves like this. Am I doing something wrong? Can anybody explain me what's happening?

like image 811
nemenos Avatar asked Oct 07 '15 08:10

nemenos


1 Answers

This is happening because SystemJS is automatically converting moment to an ES6-style module by wrapping it in a module object, while CommonJS is not.

When CommonJS pulls in moment, we get the actual moment function. This is what we've been doing in JavaScript for a while now, and it should look very familiar. It's as if you wrote:

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

When SystemJS pulls in moment, it doesn't give you the moment function. It creates an object with the moment function assigned to a property named default. It's as if you wrote:

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

Why does it do that? Because a module should be a map of one or more properties, not a function, according to ES6/TS. In ES6, the convention for massive external libraries that formerly exported themselves is to export themselves under the default property of a module object using export default (read more here; in ES6/TypeScript, you can import functions like this using the compact import moment from "moment" syntax).

You're not doing anything wrong, you just need to pick the format of your imported modules, and stick to your choice. If you want to use both CommonJS and SystemJS, you might look into configuring them to use the same import style. A search for 'systemjs default import' led me to this discussion of your issue, in which they implement the --allowSyntheticDefaultImports setting.

like image 164
mk. Avatar answered Sep 20 '22 18:09

mk.