从多个TypeScript类创建单个CommonJS模块

13

我正在尝试找出将我的应用程序拆分为几个CommonJS模块的最佳方法,以便其他应用程序可以使用。

我有5个TS类,希望将它们捆绑成一个单独的CommonJS模块。然后,我打算将此模块发布到私有NPM仓库中,以便其他应用程序可以使用。理想情况下,我希望将相关的*.d.ts定义文件与其捆绑在一起。

怎么做才是最佳方法?我正在使用外部TS模块,但这些会针对每个TS类生成一个单独的CommonJS模块。

2个回答

18
据我所知,TypeScript目前不支持合并外部模块。根据它们在CodePlex上的维基页面:
“TypeScript在外部模块源文件和它们发出的JS文件之间具有一对一的对应关系。这样做的一个影响是,无法使用--out编译器开关将多个外部模块源文件连接成单个JavaScript文件。”
但是,在TypeScript中可以通过使用内部模块来实现技巧,因为tsc编译器可以将它们编译成单个文件,然后您只需添加一个具有整个命名空间的module.exports指令的文件,就可以使其成为CommonJS模块。
以下是一个逐步示例。假设您拥有拆分为三个文件的以下内部模块:Validation.ts。
module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
}

ZipCodeValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var numberRegexp = /^[0-9]+$/;
    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

LettersOnlyValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }
}

如果你使用tsc编译器并带上--out参数编译这些文件,你可以将它们合并为一个文件。但是,这样并不会使它们成为CommonJS模块。为了导出它们,你需要使用一个技巧,添加一个名为ValidationExport.ts的ts文件,并在其中添加命名空间的导出指令:

var module: any = <any>module;
module.exports = Validation;

然后你可以运行tsc命令将所有内容编译为一个名为"validationmodule.js"的单独文件:

tsc --out validationmodule.js Validation.ts ZipCodeValidator.ts LettersOnlyValidator.ts ValidationExport.ts

输出结果是一个 CommonJS 模块,您可以在 Node.js 中使用:

var Validation = require("./validationmodule");

var zipCodeValidator = new Validation.ZipCodeValidator();
var lettersOnylValidator = new Validation.LettersOnlyValidator();

console.log(zipCodeValidator.isAcceptable("16211"));
console.log(lettersOnylValidator.isAcceptable("5555"));

内部模块只是命名空间,不应在您的代码中造成任何限制。在上面的示例中,您有脚本依赖项,并且它可以正常工作。如果您有一个更复杂的依赖关系场景无法工作,可以将其发布为问题;) - Faris Zacina
@Jthorpe,我已经更新了我的答案,并添加了一个ValidationExport.ts代码,这应该可以让编译器满意。 - Faris Zacina
1
谢谢!我正要发布一个类似的修复,使用这个声明 declare var module; 但你比我快了几秒钟... - Jthorpe
我喜欢这个简单的技巧,非常感谢。我甚至在浏览器中加载了我的JS文件。然后我得到了一个"Uncaught TypeError: Cannot set property 'exports' of undefined"的错误,所以我将我的代码改为:var module: any = <any>module || {};,似乎可以在任何地方正常工作。 - Dan Marshall
1
您的这篇帖子真是让我开心。我一直在尝试只能部分解决我的问题的解决方案,但是这个想法已经完全解决了它。谢谢!:* - Matt
显示剩余2条评论

1

每个文件都有一个单独的CommonJS模块是完全合适的。在TypeScript中的所有require调用将转换为JavaScript中的CommonJS require调用,并且.d.ts文件将在此过程中被捕获。(如果您正在做一些愚蠢的事情,比如在源目录外require类...请停止。)

只有在打算在其他应用程序中使用此NPM包时才需要考虑打包步骤,在这种情况下,请查看Browserify


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接