2014-10-29 5 views
9

Ich versuche herauszufinden, wie ich meine Anwendung in ein paar CommonJS-Module aufteilen kann, die von anderen Anwendungen genutzt werden können.Erstellen eines einzelnen CommonJS-Moduls aus mehreren TypeScript-Klassen

Ich habe 5 TS-Klassen, und ich möchte sie als ein einzelnes CommonJS-Modul bündeln. Ich beabsichtige dann, dieses Modul in einem privaten NPM Repo zu veröffentlichen, damit es von anderen Anwendungen genutzt werden kann. Idealerweise möchte ich die relevanten * .d.ts-Definitionsdateien damit verpacken.

Was ist der beste Weg, dies zu tun? Ich benutze externe TS-Module, aber diese erzeugen ein separates CommonJS-Modul pro TS-Klasse.

Antwort

14

Soweit ich weiß, unterstützt Typoskript die Kombination externer Module noch nicht. Von ihrem Wiki auf Codeplex:

TypeScript has a one-to-one correspondence between external module source files and their emitted JS files. One effect of this is that it's not possible to use the --out compiler switch to concatenate multiple external module source files into a single JavaScript file.

Sie können jedoch durch die Verwendung interne Module in Typoskript einen Trick tun, da die tsc Compiler die Fähigkeit, sie in eine einzige Datei zu kompilieren hat, und dann können Sie einfach hinzufügen eine weitere Datei mit einer module.exports Direktive für den gesamten Namespace, um daraus ein CommonJS-Modul zu machen.

Hier ist ein Schritt für Schritt Beispiel. Angenommen, Sie haben die folgende interne Module in drei Dateien aufgeteilt:

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); 
     } 
    } 
} 

Wenn Sie diese mit dem Parameter --out im tsc compiler kompilieren, können Sie sie in einer einzigen Datei kombinieren. Dies macht sie jedoch nicht zu einem CommonJS-Modul. So exportieren sie es einen Trick: eine weitere ts Datei namens ValidationExport.ts hinzufügen die Exportrichtlinie für den Namespace enthalten:

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

Und dann können Sie den Befehl ausführen tsc alles in einer einzigen Datei zu kompilieren genannt "validationmodule.js":

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

Der Ausgang ist ein Commonjs Modul, das Sie in Node.js verwenden können:

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

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

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

Danke, große Antwort.Ich denke, das führt mich dann zu der Frage: Was ist der Nachteil der Verwendung interner Module? Ich habe vor einer Weile aufgehört, sie zu verwenden, da die Verwaltung von Skriptabhängigkeiten eine Faff war. – Marcus

+0

Interne Module sind nur Namespaces. Sie sollten keine Einschränkung in Ihrem Code darstellen. In meinem Beispiel oben haben Sie Skriptabhängigkeiten und es funktioniert gut. Wenn Sie ein komplexeres Abhängigkeitsszenario haben, das nicht funktioniert hat, können Sie es als Frage stellen;) –

+0

Ich habe Probleme bei der Implementierung dieser Lösung. Insbesondere, wenn ich die Zeile 'tsc --out validationmodule.js Validation.ts [...] ValidationExport.ts' ausfühle, löst tsc den Fehler 'TS2304: Name des Namens nicht finden 'aus, wenn es versucht,' ValidationExport' zu verarbeiten .ts' – Jthorpe

1

Having ein separates CommonJS-Modul pro Datei ist völlig angemessen. Alle require Aufrufe in TypeScript werden CommonJS require Aufrufe in JavaScript übersetzt, und die .d.ts Dateien werden dabei abgeholt. (Wenn Sie etwas Dummes wie require ing-Klassen außerhalb Ihres Quellverzeichnisses tun ... stoppen.)

Sie müssten nur einen Verpackungsschritt in Betracht ziehen, wenn Sie dieses NPM-Paket in anderen Anwendungen verwenden möchten schauen Sie in Browserify