Создание единого модуля CommonJS из нескольких классов TypeScript

Я пытаюсь найти лучший способ разделить мое приложение на несколько модулей CommonJS, которые могут использоваться другими приложениями.

У меня есть 5 классов TS, и я хотел бы объединить их в один модуль CommonJS. Затем я намерен опубликовать этот модуль в частном репозитории NPM, чтобы его могли использовать другие приложения. В идеале я хотел бы упаковать с ним соответствующие файлы определения *.d.ts.

Как лучше всего это сделать? Я использую внешние модули TS, но они создают отдельный модуль CommonJS для каждого класса TS.


person LJW    schedule 29.10.2014    source источник


Ответы (2)


Насколько я знаю, typescript пока не поддерживает объединение внешних модулей. Из их вики на codeplex:

TypeScript имеет взаимно однозначное соответствие между исходными файлами внешних модулей и созданными ими JS-файлами. Одним из последствий этого является то, что невозможно использовать параметр компилятора --out для объединения нескольких исходных файлов внешних модулей в один файл JavaScript.

Однако вы можете пойти на хитрость, используя внутренние модули в машинописном тексте, так как компилятор 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);
        }
    }
}

Если вы скомпилируете их с параметром --out в tsc compiler, вы сможете объединить их в один файл. Однако это не делает их модулем CommonJS. Чтобы экспортировать их, вы используете трюк, чтобы добавить еще один файл ts с именем ValidationExport.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"));
person Faris Zacina    schedule 29.10.2014
comment
Спасибо, отличный ответ. Я думаю, это приводит меня к вопросу: в чем недостаток использования внутренних модулей? Я перестал их использовать некоторое время назад, так как управление зависимостями скриптов было пустяком. - person LJW; 29.10.2014
comment
Внутренние модули — это просто пространства имен. Они не должны создавать никаких ограничений в вашем коде. В моем примере выше у вас есть зависимости скрипта, и он отлично работает. Если у вас есть более сложный сценарий зависимости, который не сработал, вы можете опубликовать его как вопрос;) - person Faris Zacina; 29.10.2014
comment
У меня возникли проблемы с реализацией этого решения. В частности, когда я запускаю строку tsc --out validationmodule.js Validation.ts [...] ValidationExport.ts, tsc выдает ошибку TS2304: Cannot find name 'module'. при попытке обработать ValidationExport.ts - person Jthorpe; 22.03.2015
comment
@Jthorpe Я обновил свой ответ кодом ValidationExport.ts, который должен порадовать компилятор. - person Faris Zacina; 22.03.2015
comment
Спасибо! Я как раз собирался опубликовать аналогичное исправление, используя это объявление declare var module;, но вы опередили меня на несколько секунд... - person Jthorpe; 22.03.2015
comment
Мне нравится простой трюк, большое спасибо. Я даже загрузил свой js-файл в браузере. Там я получил Uncaught TypeError: Cannot set property 'exports' of undefined, поэтому я изменил свою строку на: var module: any = <any>module || {}; и, кажется, работает везде. - person Dan Marshall; 15.05.2015
comment
Вы, сэр, сделали мой день этим постом. Я пробовал решения, которые лишь частично решают мои проблемы, но эта идея сделала это на 100%. Спасибо! :* - person Matt; 04.09.2016

Наличие отдельного модуля CommonJS для каждого файла вполне уместно. Все вызовы require в TypeScript будут преобразованы в вызовы require CommonJS в JavaScript, а файлы .d.ts будут выбраны в процессе. (Если вы делаете что-то глупое, например, requireing классы за пределами вашего исходного каталога... остановитесь.)

Вам нужно будет рассмотреть этап упаковки только в том случае, если вы собираетесь использовать этот пакет NPM в других приложениях, и в этом случае загляните в Browserify

person nexus    schedule 30.10.2014