对 TypeScript 模块感到困惑

Confused about TypeScript modules

我是 TypeScript 的新手,但有 C# 背景,我对如何处理 TypeScript 模块有点困惑。我一直在考虑将模块作为 C# 中的名称空间,但也许这是错误的,因为我的代码没有按我预期的方式运行。

我有以下文件夹结构:

|-myApp
|  |-myController
|  |      |-myController.ts
|  |-models
       |-a.ts
       |-b.ts

和这段代码:

// a.ts
module MyApp.Models {
    export class A {

    }
}
// b.ts
module MyApp.Models {
    export class B {

    }
}

// myController.ts (THIS DOESN'T WORK)
module MyApp.MyController {
    import Models = MyApp.Models;
    class MyController {
        a = new Models.A();
        b = new Models.B();
    }
}

// myController.ts (THIS WORKS)
module MyApp.MyController {
    class MyController {
        a = new Models.A();
        b = new Models.B();
    }
}

在上面的示例中,我尝试导入模块(命名空间?)模型将在运行时导致错误,因为模型未定义。但是,如果我删除导入语句,代码将正常工作。我可能没有想清楚并且犯了一些非常愚蠢的初学者错误,但是有人可以告诉我我做错了什么以及在我的特定场景中使用模块的最佳方法是什么。为什么如果我删除导入但不使用它,它会起作用?

问候克里斯托弗

Typescript 模块类似于 C# 命名空间。他们帮助组织代码库。

import 语句可用于两件事:提供别名或导入外部模块。

要创建别名,您可以像以前一样使用导入:

import Models = App.Models;

要导入您使用的外部模块:

import Models = './path/to/module';

我不明白为什么你的代码不起作用。我试图在我的机器上重现它,但两个控制器都适合我。

抱歉回答晚了。

围绕 modules/namespaces 的问题和魔力发生在三件事上:

  1. 您的系统 - 由于您的系统,TypeScript 编译器以不同的方式发现文件,当它将您的源代码编译为 JS 代码时,它会占据一席之地,因为相同的 ts 文件提供不同的结果 JS。
  2. 理解魔术语句/// <reference path="***"/>。如果没有额外的 Module System 像 AMD 或 System.js 等,那么使用这个词是非常重要的。因为如果你使用它发生合并编译,因为它告诉编译器应该以什么顺序编译文件。
  3. 了解TypeScript在编译后的JS文件中提出的JS执行和结构。考虑下一个例子 - (这是你编译成 JS 的例子)

        var MyApp;
        (//functon wrapping
         function (MyApp) {//function declaration 
            var MyController;
            (function (MyController_1) {
                var Models = MyApp.Models;
                var MyController = (function () {
                    function MyController() {
                        this.a = new Models.A();
                        this.b = new Models.B();
                    }
                    return MyController;
                })();
                MyController_1.MyController = MyController;
            })(MyController = MyApp.MyController || (MyApp.MyController = {}));
        }
        )(MyApp || (MyApp = {}));// end of function wrapping and it execution
        /// <reference path="myApp/MyController/myController.ts"/>
    
        new MyApp.MyController.MyController(); // createing new instance of MyController
    
        var MyApp;
        (function (MyApp) {
            var Models;
            (function (Models) {
                var B = (function () {
                    function B() {
                    }
                    return B;
                })();
                Models.B = B;
            })(Models = MyApp.Models || (MyApp.Models = {}));
        })(MyApp || (MyApp = {}));
        var MyApp;
        (function (MyApp) {
            var Models;
            (function (Models) {
                var A = (function () {
                    function A() {
                    }
                    return A;
                })();
                Models.A = A;
            })(Models = MyApp.Models || (MyApp.Models = {}));
        })(MyApp || (MyApp = {}));
        //# sourceMappingURL=app.js.map
    

    如果你深入研究 JS,你会发现 JS 代码按下一个顺序执行

    • 读取函数并传入内存
    • 正在执行另一个代码

    这就是为什么下一个代码可以工作的原因

     myFunction();
    
     function myFunctuion(){};
    

    由于模块的 typescript JS 构建技术和 classes 它使用这样的匿名函数:

    var MyApp;
        (//functon wrapping
         function (MyApp) {//function declaration 
            var MyController;
            (function (MyController_1) {
                var Models = MyApp.Models;
                var MyController = (function () {
                    function MyController() {
                        this.a = new Models.A();
                        this.b = new Models.B();
                    }
                    return MyController;
                })();
                MyController_1.MyController = MyController;
            })(MyController = MyApp.MyController || (MyApp.MyController =  {}));
    

    在这种情况下调用 like next 会导致运行时异常,因为之前没有执行过 anonimus 块。

      MyController(); // here runtime exception
    
      var MyController = (function () {
                    function MyController() {
                        this.a = new Models.A();
                        this.b = new Models.B();
                    }
                    return MyController;
                })();
    

    现在,回到我们的示例并发现它,正如您之前看到的 MyController 定义的那样,我们执行匿名函数和名为 MyController 的变量现在存在于全局范围内。 下一步是执行 MyController class 的构造函数,在其中我们找到接下来的两部分代码

           this.a = new Models.A();
           this.b = new Models.B();
    

    但是这里报错了,因为由变量Modules和class组成的匿名函数AB还没有执行。这就是为什么此时我们收到变量模块未定义的错误。

希望这个话题能让你更好地了解JS和TS,对你的新特性有所帮助!!!

祝你好运!

P.S。 Here is working example