2014-10-29 7 views
9

Sto cercando di elaborare il metodo migliore per dividere la mia applicazione in alcuni moduli CommonJS che possono essere utilizzati da altre applicazioni.Creazione di un singolo modulo CommonJS da diverse classi TypeScript

Ho 5 classi TS e mi piacerebbe raggrupparle come un singolo modulo CommonJS. Quindi intendo pubblicare questo modulo su un repository NPM privato, in modo che possa essere utilizzato da altre applicazioni. Idealmente mi piacerebbe impacchettare i relativi file di definizione * .d.ts.

Qual è il modo migliore per farlo? Sto usando moduli TS esterni, ma questi producono un modulo CommonJS separato per classe TS.

risposta

14

Per quanto ne so, il dattiloscritto non supporta ancora la combinazione di moduli esterni. Dal loro wiki su 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.

Tuttavia, si può fare un trucco utilizzando moduli interni a macchina, dal momento che il compilatore TSC ha la possibilità di compilarli in un singolo file, e quindi si può semplicemente aggiungere un altro file con una direttiva module.exports per l'intero spazio dei nomi per renderlo un modulo CommonJS.

Ecco un esempio dettagliato. Diciamo che avete i seguenti moduli interni diviso in tre file:

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

Se si compila questi con il parametro --out nello tsc compiler, è possibile combinarli in un singolo file. Tuttavia, questo non li rende un modulo CommonJS. Per esportare li si usa un trucco per aggiungere un altro file di TS chiamati ValidationExport.ts contenenti la direttiva di esportazione per lo spazio dei nomi:

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

E poi si può eseguire il comando TSC di compilare tutto in un unico file denominato "validationmodule.js":

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

L'uscita è un modulo CommonJS è possibile utilizzare in 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")); 
+0

Grazie, ottima risposta.Immagino che questo mi porti alla domanda: qual è lo svantaggio di utilizzare i moduli interni? Ho smesso di usarli un po 'di tempo fa perché gestire le dipendenze degli script era un problema. – Marcus

+0

I moduli interni sono solo spazi dei nomi. Non dovrebbero porre alcuna limitazione nel codice. Nel mio esempio sopra hai dipendenze di script e funziona bene. Se hai uno scenario di dipendenza più complesso che non ha funzionato, puoi postarlo come domanda;) –

+0

Ho problemi a implementare questa soluzione. In particolare, quando eseguo la riga 'tsc --out validationmodule.js Validation.ts [...] ValidationExport.ts', tsc solleva l'errore' TS2304: Impossibile trovare il nome 'module''. Quando tenta di elaborare 'ValidationExport .ts' – Jthorpe

1

Avere un modulo CommonJS separato per file è completamente appropriato. Tutte le chiamate require in TypeScript si tradurranno in chiamate CommonJS require in JavaScript e i file .d.ts verranno prelevati nel processo. (Se stai facendo qualcosa di sciocco come le classi require fuori dalla tua directory sorgente ... stop.)

Avresti solo bisogno di prendere in considerazione una fase di confezionamento se intendevi usare questo pacchetto NPM in altre applicazioni, nel qual caso guarda su Browserify