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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12790262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:14:03  来源:igfitidea点击:

How to spread module across multiple AMD files?

typescript

提问by IgorM

I can't figure out if it even possible to have an "export module" spread accross multiple files.

我不知道是否有可能将“导出模块”分布在多个文件中。

If I have file Contact.ts:

如果我有文件 Contact.ts:

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

and another ContactView.ts

和另一个 ContactView.ts

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

Then TSC is not recognizing the Contact class. As you can see the Contact and the ContactView are declared to reside in the same module and according to the spec it should work.

那么 TSC 无法识别 Contact 类。如您所见,Contact 和 ContactView 被声明为驻留在同一个模块中,并且根据规范它应该可以工作。

I'm building a composite app that uses the require.js and AMD patterns so I HAVE to use the "export module" declaration.

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

Should I do some type of "ahead declaration" or some tricky "import" ?

我应该做某种类型的“提前声明”还是一些棘手的“导入”?

Thanks for the advise.

谢谢你的建议。

EDIT: Currently I load each module separately via import, but, if you'll notice, it creates an enormous waste of code and lot of "import" dependencies. My question was if there is a way to use the same namespace (i.e. Contacts) to let know the TS that I do not mean to import. I was looking into the normal // command, but it doesn't work. I even tried the *.d.ts declaration files with no success so far.

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

回答by nxn

The spec allows you to define internalmodules across multiple files (in essence, internal modules refer to the javascript module pattern). Externalmodules, such as AMD or CommonJS modules, work on the idea that each file is the actual "module of code", and the namespacing/naming within it is irrelevant since the module will be loaded into its own new object anyway.

该规范允许您跨多个文件定义内部模块(本质上,内部模块指的是 javascript 模块模式)。外部模块(例如 AMD 或 CommonJS 模块)的工作原理是每个文件都是实际的“代码模块”,并且其中的命名空间/命名无关紧要,因为无论如何模块都会被加载到自己的新对象中。

You could write the following code to load the Contact.ts module inside of the ContactView.ts module:

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

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

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

And that should work well enough, but if you wanted to have access to the contents of both modules in another area (to for example make a new Contact model yourself), you would have to essentially import both of them:

这应该工作得很好,但是如果您想访问另一个区域中两个模块的内容(例如,自己创建一个新的 Contact 模型),您实际上必须导入它们:

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

Which I think is fine enough, because you're clearly stating your dependencies. The downside is that they wont share a common parent object, so having them both be in a "Contact" module-pattern probably isn't of great use.

我认为这已经足够了,因为您清楚地说明了您的依赖关系。缺点是它们不会共享一个共同的父对象,所以让它们都处于“联系”模块模式可能没有多大用处。

Another option is to export "Contact" along with "ContactView", as follows (granted this code is kind of silly because you're already doing exactly that via the model property of ContactView, but never the less...):

另一种选择是将“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;
}

So you'd be able to access it after having loaded ContactView.

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

EDIT: By the way, you aren't limited to only exporting modules via "export module Name { ... }", you can export anything as the file itself is the module. So you could have a file which just has "export function foo() { ... }" without any module-pattern code wrapping it.

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

EDIT2: It looks like AMD might have functionality for loading multiple dependencies and constructing "modules" from those, but I have no idea how that would work in TS, here's a link that goes over that: http://www.adobe.com/devnet/html5/articles/javascript-architecture-requirejs-dependency-management.html(Constructor modules).

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

回答by Morten Mertner

I struggled with the same question for a while, and just wanted to share what I am doing in case anyone else wanders across this question.

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

First, I defined myself a reference file that declares all of the files in my module:

首先,我为自己定义了一个引用文件,该文件声明了我的模块中的所有文件:

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

Note that paths specified inside the file are relative to the location of the reference file itself (_contacts.ts), unlike a .jsreference file. My directory structure looks like this:

请注意_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

Back to the reference file itself. The first line includes a separate reference file listing all of the external libraries used by the module, such as underscore, moment or any other existing library you have a .d.tsdefinition file for. The remaining lines are the files that make up the module.

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

Inside every file that is part of the module, I reference the above file:

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

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

Similarly, you can create a single reference file to list all your modules:

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

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

And simply point to this from your source files.

只需从您的源文件中指向它即可。

This does not solve the problem of the emitted code being in separate files, though. For that problem I am using a JavaScript minification tool, which is capable of bundling up multiple files into a single source file. Depending on your compilation settings and use case needs, you may need to apply some wrapper around the generated code for it to work as an AMD module (not too familiar with that part yet).

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