Search code examples
typescriptmoduleecmascript-6systemjstsc

How to export a TypeScript module for SystemJS?


On my website I want to import a FancyModule using SystemJS, so that I can create instances of classes which this module exports.

So what I want to achieve is this (within a ECMAScript 2015-compatible website):

SystemJS.import('MyFancyModule').then(function(MyFancyModule) {
  var myFancyInstance = new MyFancyModule.MyFancyClass('Test');
  console.log(myFancyInstance.text);
});

Unfortunately, I am getting the following error:

TypeError: MyFancyModule.MyFancyClass is not a constructor(…)

Here is my TypeScript module:

export module MyFancyModule {
  export class MyFancyClass {
    public text: string;

    constructor(text: string) {
      this.text = text;
    }
  }
}

And this is my TypeScript compiler setting (tsconfig.json):

{
  "compilerOptions": {
    "module": "system",
    "moduleResolution": "node",
    "outFile": "dist/browser/MyFancyModule.js",
    "rootDir": "src/ts",
    "target": "es5"
  }
}

Which compiles my TypeScript module into:

System.register("MyFancyModule", [], function(exports_1, context_1) {
  "use strict";
  var __moduleName = context_1 && context_1.id;
  var MyFancyModule;
  return {
    setters: [],
    execute: function() {
      (function(MyFancyModule) {
        var MyFancyClass = (function() {
          function MyFancyClass(text) {
            this.text = text;
          }

          return MyFancyClass;
        }());
        MyFancyModule.MyFancyClass = MyFancyClass;
      })(MyFancyModule = MyFancyModule || (MyFancyModule = {}));
      exports_1("MyFancyModule", MyFancyModule);
    }
  }
});

For me it looks like MyFancyModule is properly exported but I don't know why I cannot access the MyFancyClass.


Solution

  • I think I managed to reproduce your example.

    It looks like with this setup, the file - MyFancyModule.ts - is already a module in itself. When you do

    export module MyFancyModule {
    

    you create a nested module within it.

    This code should work with everything else unchanged:

        SystemJS.import('MyFancyModule').then(function(MyFancyModule) {
            var myFancyInstance = new MyFancyModule.MyFancyModule.MyFancyClass('Test');
            console.log(myFancyInstance.text);
        });
    

    Alternatively, you can remove export module from the .ts file and have export class at the top level - then your original import will work.