Как экспортировать модуль TypeScript для SystemJS?

На своем веб-сайте я хочу импортировать FancyModule с помощью SystemJS, чтобы я мог создавать экземпляры классов, которые этот модуль экспорт.

Итак, чего я хочу добиться, так это (на веб-сайте, совместимом с ECMAScript 2015):

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

К сожалению, я получаю следующую ошибку:

TypeError: MyFancyModule.MyFancyClass не является конструктором (…)

Вот мой модуль TypeScript:

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

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

А это моя настройка компилятора TypeScript (tsconfig.json):

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

Который компилирует мой модуль TypeScript в:

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);
    }
  }
});

Мне кажется, что MyFancyModule экспортируется правильно, но я не знаю, почему я не могу получить доступ к файлу MyFancyClass.


person Benny Neugebauer    schedule 24.08.2016    source источник


Ответы (2)


Думаю, мне удалось воспроизвести ваш пример.

Похоже, что при такой настройке файл — MyFancyModule.ts — уже сам по себе является модулем. Когда вы делаете

export module MyFancyModule {

вы создаете в нем вложенный модуль.

Этот код должен работать со всем остальным без изменений:

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

Кроме того, вы можете удалить export module из файла .ts и оставить export class на верхнем уровне — тогда ваш исходный импорт будет работать.

person artem    schedule 25.08.2016
comment
Это было проблемой! Спасибо. :) - person Benny Neugebauer; 25.08.2016
comment
— Не могли бы вы взглянуть на github.com/bennyn/systemjs-example? Я подтолкнул проект туда и удалил export module MyFancyModule из кода TypeScript, но он все еще не работает. :'( - person Benny Neugebauer; 26.08.2016
comment
Я не знаю почему, но это работает, только если имя модуля в SystemJS.import точно совпадает с именем в SystemJS.register, поэтому вам нужно сделать это: SystemJS.config({map: {MyFancyModule: 'js/MyFancyModule.js'}}); SystemJS.import('MyFancyModule'). я создал пиар - person artem; 26.08.2016

Typescript позаботится о том, как загружать модули из различных модульных систем, которые он поддерживает.
Идея состоит в том, что у вас есть специальный синтаксис для этого (в машинописи) и на основе модуля, который вы указываете компилятору (например, в tsconfig.json) он сгенерирует соответствующий код для загрузки модулей в соответствии с выбранной системой модулей.

Итак, все, что вам нужно сделать, это:

import * as MyFancyModule from "MyFancyModule";

var myFancyInstance = new MyFancyModule.MyFancyClass('Test');
console.log(myFancyInstance.text);

Редактировать

Компилятор должен сгенерировать что-то вроде:

System.register(["MyFancyModule"], function(exports_1, context_1) {
    "use strict";
    var __moduleName = context_1 && context_1.id;
    var MyFancyModule;
    var myFancyInstance;
    return {
        setters:[
            function (MyFancyModule_1) {
                MyFancyModule = MyFancyModule_1;
            }],
        execute: function() {
            myFancyInstance = new MyFancyModule.MyFancyClass('Test');
            console.log(myFancyInstance.text);
        }
    }
});

Как видите, в скомпилированном js нет следов этого синтаксиса import from.

person Nitzan Tomer    schedule 24.08.2016
comment
Но import * as MyFancyModule from "MyFancyModule"; не определено в Спецификации языка ECMAScript 2015, не так ли? Потому что я хочу выполнить SystemJS.import на веб-сайте ES5. - person Benny Neugebauer; 24.08.2016
comment
ECMAScript 2015 Language Specification также не поддерживает типы, но машинописный текст поддерживает. То же самое с тем, как вы импортируете вещи в машинописный текст. Он компилирует ваш исходный код в действительный js на основе целевой системы и системы модулей по вашему выбору. Подробнее об импорте модулей можно прочитать в официальной документации: Модули › Импорт< /а> - person Nitzan Tomer; 24.08.2016
comment
Я обновил свой ответ скомпилированным js, который показывает, что часть import from - это просто ts. - person Nitzan Tomer; 24.08.2016
comment
Спасибо, Ницан, но это все еще то, что я ищу. Я не хочу, чтобы зарегистрированный модуль уже создавал экземпляр и выполнял console.log. Я просто хочу, чтобы модуль открывал свои классы приложению, которое импортирует модуль. - person Benny Neugebauer; 24.08.2016