【问题标题】:How to export a TypeScript module for SystemJS?如何为 SystemJS 导出 TypeScript 模块?
【发布时间】:2016-12-31 10:15:45
【问题描述】:

在我的网站上,我想使用SystemJS 导入FancyModule,以便我可以创建此模块导出的类的实例。

所以我想要实现的是(在与 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

【问题讨论】:

    标签: typescript module ecmascript-6 systemjs tsc


    【解决方案1】:

    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 语法的痕迹。

    【讨论】:

    • 但是 import * as MyFancyModule from "MyFancyModule"; 没有在 ECMAScript 2015 语言规范中定义,是吗?因为我想在 ES5 网站内执行SystemJS.import
    • ECMAScript 2015 Language Specification 也不支持类型,但 typescript 支持。与您在 typescript 中导入内容的方式相同。它根据您选择的目标和模块系统将您的源代码编译为有效的 js。您可以在官方文档中阅读有关如何导入模块的更多信息:Modules > Import
    • 我用编译后的 js 更新了我的答案,这表明 import from 部分只是 ts。
    • 感谢 Nitzan,但它现在仍然是我正在寻找的东西。我不希望注册的模块已经创建了实例并执行了console.log。我只希望模块将其类公开给导入模块的应用程序。
    【解决方案2】:

    我想我设法重现了你的例子。

    在这种设置下,文件 - MyFancyModule.ts - 本身已经是一个模块。当你这样做

    export module MyFancyModule {
    

    您在其中创建一个嵌套模块。

    此代码应该可以在其他所有内容不变的情况下使用:

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

    或者,您可以从 .ts 文件中删除 export module 并在顶层添加 export class - 然后您的原始导入将起作用。

    【讨论】:

    • 这就是问题所在!谢谢你。 :)
    • ——你能看看github.com/bennyn/systemjs-example吗?我把项目推到那里,从 TypeScript 代码中删除了export module MyFancyModule,但它仍然不起作用。 :'(
    • 我不知道原因,但它只有在 SystemJS.import 中的模块名称与 SystemJS.register 中的名称完全匹配时才有效,因此您需要这样做:SystemJS.config({map: {MyFancyModule: 'js/MyFancyModule.js'}}); SystemJS.import('MyFancyModule')。我创建了一个 PR
    猜你喜欢
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2016-10-25
    • 1970-01-01
    • 2016-12-06
    • 2022-11-26
    相关资源
    最近更新 更多