如何在多个AMD文件中传播模块?

时间:2012-10-08 22:18:13

标签: typescript

我无法弄清楚是否有可能拥有一个"导出模块"分布在多个文件中。

如果我有文件Contact.ts:

// file Contact.ts
export module Contacts {
   export class Contact {
      ...
   }
}

和另一个ContactView.ts

// file ContactView.ts
export module Contacts {
   export class ContactView {
      model: Contact;  // <---  is not recognized
   }
}

然后TSC无法识别Contact类。正如您所看到的那样,Contact和ContactView被声明为驻留在同一个模块中,并且根据规范应该有效。

我正在构建一个使用require.js和AMD模式的复合应用程序,所以我必须使用&#34;导出模块&#34;声明。

我应该做某种类型的&#34;提前声明&#34;或者一些棘手的&#34;导入&#34; ?

感谢您的建议。

编辑:目前我通过导入单独加载每个模块,但是,如果您注意到,它会造成巨大的代码浪费和大量的导入&#34;依赖。 我的问题是,是否有办法使用相同的命名空间(即联系人)来让我知道我不想导入的TS。 我正在调查正常的//命令,但它不起作用。到目前为止,我甚至尝试了* .d.ts声明文件,但没有成功。

2 个答案:

答案 0 :(得分:6)

规范允许您跨多个文件定义内部模块(本质上,内部模块引用javascript模块模式)。 外部模块,例如AMD或CommonJS模块,认为每个文件都是实际的“代码模块”,并且其中的命名空间/命名是无关紧要的,因为模块将被加载到其中无论如何都拥有新的物品。

您可以编写以下代码来加载ContactView.ts模块中的Contact.ts模块:

// file ContactView.ts    
import mod = module("./Contact");

export module Contacts {
   export class ContactView {
      model: mod.Contacts.Contact;  // <---  will be recognized
   }
}

这应该可以运行得很好,但是如果你想访问另一个区域中的两个模块的内容(例如自己制作一个新的Contact模型),你必须基本上导入它们:

import c = module("./Contact");
import cv = module("./ContactView");

我认为这很好,因为你明确说明了你的依赖关系。缺点是它们不会共享一个共同的父对象,所以让它们都处于“联系”模块模式可能没什么用处。

另一种选择是将“Contact”与“ContactView”一起导出,如下所示(授予此代码有点愚蠢,因为您已经通过ContactView的模型属性完成了这一操作,但从未如此......) :

export module Contacts {
   export class ContactView {
       model: mod.Contacts.Contact;
       constructor() {
           this.model = new mod.Contacts.Contact();
       }
    }

    export var Contact = mod.Contacts.Contact;
}

因此,您可以在加载ContactView后访问它。

编辑:顺便说一句,您不仅限于通过“导出模块名称{...}”导出模块,您可以导出任何内容,因为文件本身就是模块。所以你可以拥有一个只有“export function foo(){...}”的文件,而不包含任何模块模式代码。

EDIT2:看起来AMD可能具有加载多个依赖项和构建“模块”的功能,但我不知道这在TS中是如何工作的,这里有一个链接:http://www.adobe.com/devnet/html5/articles/javascript-architecture-requirejs-dependency-management.html(构造函数模块)。

答案 1 :(得分:4)

我在同一个问题上挣扎了一段时间,只是想分享我正在做的事情以防其他人在这个问题上徘徊。

首先,我自己定义了一个参数文件,声明了我模块中的所有文件:

/// <reference path="_contacts.dependencies.ts" />
/// <reference path="../contacts/Contact.ts" />
/// <reference path="../contacts/ContactView.ts" />
/// <reference path="../contacts/ContactModel.ts" />

请注意,与_contacts.ts引用文件不同,文件内指定的路径相对于引用文件本身的位置(.js)。我的目录结构如下所示:

modules
    references // all of the reference files
        knockout 
        underscore
        // ... a subfolder for every 3rd party library used
    contacts
    commerce 
    // ... other modules at same level as contacts

返回参考文件本身。第一行包含一个单独的参考文件,其中列出了模块使用的所有外部库,例如下划线,时刻或您拥有.d.ts定义文件的任何其他现有库。其余行是组成模块的文件。

在作为模块一部分的每个文件中,我引用了上面的文件:

/// <reference path="../references/_contacts.ts" />
module Contacts {
    export class Contact { 
        public model: ContactModel;
        // ...
    }
} 

同样,您可以创建一个参考文件来列出所有模块:

/// <reference path="_address.ts" />
/// <reference path="_contacts.ts" />
/// <reference path="_commerce.ts" />

只需从源文件中指出这一点。

但这并不能解决发出的代码在单独文件中的问题。对于这个问题,我使用的是JavaScript缩小工具,它能够将多个文件捆绑到一个源文件中。根据您的编译设置和用例需求,您可能需要在生成的代码周围应用一些包装器,以使其作为AMD模块工作(尚不太熟悉该部分)。