10

I've finished porting a JavaScript library to TypeScript in Visual Studio 2012. All in all its about 60 classes, with each class defined in its own .ts file.

All classes are defined in the same module. I use reference comments to reder to classes defined in other files. The layout of every file looks like this:

///<reference path='./../myotherclass.ts' />

module MyModule {

    export class MyClass {
        ...
    }

}

Now I've created a second project in the same solution which is going to be the actual application using my newly ported library. I have to include my library somehow and I guess that's what the module system is for. However, I'm not sure what file(s) to import as MyModule is spread over dozens of files. Is this what I can use the .d.ts file for?

Also, to be able to import a module, it has to be declared with the 'export' keyword but if I do that then it is not found by reference comments anymore.

On top of all that, both projects should be compiled so that the compiler output can be readily used with a module loader like requireJS.

What's the best approach to accomplish all this?

Thank you!

4

1 回答 1

9

好的,让我首先说“模块”可以表示不同的东西。例如,您的“MyModule”创建了“模块模式”。据我所知,TypeScript 在语言规范中将这些称为“内部模块”,它们与您将使用 RequireJS 之类的东西加载的“外部模块”不同。主要区别在于外部模块期望拥有自己的隔离环境,其中包含可用于导出其功能的预定义“导出”对象。

看看你的模块的输出:

var MyModule;
(function (MyModule) {
    var MyClass = (function () {
        function MyClass() { }
        return MyClass;
    })();
    MyModule.MyClass = MyClass;    
})(MyModule || (MyModule = {}));

您会看到它正在将内容导出到“MyModule”中,这将对您加载的其他脚本文件全局可用,例如,html“脚本”块。由于您提到您有 60 个,您可能还可以将编译器设置为输出一个可以包含在标记中的文件,而不是一个一个地加载每个文件。

继续,看看如果将模块声明从“module MyModule { ... }”更改为“export module MyModule { ... }”,输出会发生什么:

(function (MyModule) {
    var MyClass = (function () {
        function MyClass() { }
        return MyClass;
    })();
    MyModule.MyClass = MyClass;    
})(exports.MyModule || (exports.MyModule = {}));

如您所见,您的模块仍在使用“模块模式”,但它被分配为“exports”的成员,这意味着它应该被加载,例如,节点的“require”函数。

在这种情况下,您可能希望通过以下代码实际使用您的模块:

import wrapper = module("./MyModule");
var instance = new wrapper.MyModule.MyClass();

请注意,“./MyModule”名称实际上是指定义模块的文件名(减去 .js 扩展名)(这就是 VS 说它无法为您找到这些模块的原因)。代码应编译为:

var wrapper = require("./MyModule");
var instance = new wrapper.MyModule.MyClass();

除此之外,您甚至不再需要对“模块”关键字做任何事情来拥有一个模块。您可以简单地导出一个函数:

// foo.ts
export function foo() {
    ...
};

// some other file in the same dir
import wrapper = module("./foo");
var result = wrapper.foo();

这是有效的,因为函数 'foo' 将直接分配给“exports”,该函数将在另一个文件中别名为“wrapper”。

为了进一步增加与模块相关的混乱混乱,我还应该提到 AMD 模块仍然不同,因为它们是异步加载的,与节点的“要求”不同。要让 TypeScript 输出这些内容,您需要将“--module AMD”参数传递给编译器。

无论如何,我希望我能很好地解释这种情况,以至于你能够弄清楚你到底需要/想要什么。您最终使用的模块类型实际上取决于您将如何使用它们……即节点、Web 或两者的混合。

于 2012-10-07T19:22:22.860 回答