Использование пространства имен, распределенного по нескольким файлам модулей в TypeScript
Я начал работу над масштабным проектом машинописи.
С самого начала я хочу, чтобы мои файлы были организованы (этот проект будет разделен между многими разработчиками, поэтому порядок очень необходим).
Я пытался использовать модули/пространства имен и разделять классы на отдельные файлы для каждого с папкой, содержащей пространство имен.
Структура файла:
app.ts
\Classes
---- \Animals
---- ---- Mammals.ts
---- ---- Reptiles.ts
Затем я пытаюсь импортировать все файлы в этом пространстве имен в app.ts, используя что-то вроде: import * as Animals from "./Classes/Animals"
Что касается самих файлов пространства имен, я попробовал следующее, но безуспешно:
namespace Animals {
export class Mammals {
constructor() {
}
}
}
а также:
module Animals {
export class Reptiles {
constructor() {
}
}
}
К сожалению, путь никогда не распознается (так как он указывает на папку, а не на один файл). Это вообще возможно? Наличие всех моих классов из одного пространства имен в одном файле приведет к файлам длиной в тысячи строк и для этого проекта, которые невозможно обслуживать.
Я также заметил, что TypeScript 1.5 имеет поддержку tsconfig.json - однако, добавление каждого файла вручную на карту является верным способом возникновения проблем, когда разработчики начинают добавлять классы.
ПРИМЕЧАНИЕ. Я использую Visual Studio 2015, TypeScript 1.5 (я не уверен, как это проверить). У меня также включена поддержка ES6.
Ответы
Ответ 1
Используйте реэкспортирование для создания внешнего модуля, который группирует и предоставляет типы из других модулей:
// Classes/Animals.ts
export * from '.\Animals\Mammals';
export * from '.\Animals\Reptiles';
Затем импортируйте типы из нового модуля, как обычно:
// app.ts
import * as Animals from '.\Classes\Animals'
let dog: Animals.Dog;
let snake: Animals.Snake;
или
// app.ts
import { Dog, Snake } from '.\Classes\Animals'
let dog: Dog;
let snake: Snake;
Ответ 2
Нашел способ достичь своей цели, но не с помощью ключевого слова пространства имен.
- Классы "Животные", Animal.ts & Mammal.ts & Reptile.ts в пространстве имен.
- с index.ts для барреля.
- animals.ts для группировки пространства имен.
![Animal namespace]()
Образцы классов:
![Classes]()
index.ts (как баррель)
![enter image description here]()
animals.ts (для группировки пространства имен)
![enter image description here]()
И здесь вы идете о концепции пространства имен.
![enter image description here]()
Ответ 3
Внешние модули подразумевают, что вы загружаете файлы по файлу. И AMD, и CommonJS не имеют такой вещи, как пространство имен. Вы можете использовать некоторую постобработку для связывания файлов в одном модуле.
Далее определяется внутренний модуль:
module Animals {
export class Reptiles {
constructor() {
}
}
}
Вы не должны использовать для этого import
. Animals.Reptiles
отображается везде. Единственная цель - загрузить скрипты в правильном порядке (например, базовые классы перед наследниками). Поэтому вы должны перечислить все файлы в ts.config
или в другом месте. В моем проекте я использую пакеты в папках и соглашусь добавить @
в имена файлов базовых классов.
Другим решением является использование внешних модулей: AMD (RequireJS) или CommonJS (Browserify). В этом случае удалите верхний уровень module
из объявления. Если один файл содержит только один тип, вы можете экспортировать его как корень:
class Reptiles {
constructor() {
}
}
export = Reptiles;
Вы можете ссылаться на модуль по пути к файлу:
import Reptilies = require('..\Animals\Reptilies')
var reptile = new Reptile();
Или с новыми модулями ES6:
export class Reptiles {
constructor() {
}
}
import { Reptiles } from '..\Animals\Reptilies';
Ответ 4
Кажется, что нет способа сделать это, используя пространства имен самостоятельно (если вы не хотите использовать модуль Augmentation и declare
каждый новый элемент для добавления отдельно); однако пространство имен может быть частью класса, который может быть расширен! Это лучшая альтернатива, которую я могу найти:
CoreLibraryTypes.ts
abstract class Types { }
namespace Types {
export class TypeA { }
export class TypeB { }
export class TypeC { }
}
export { Types };
CoreTypesExtended.ts
import CoreLibraryTypes from "./CoreLibraryTypes";
abstract class Types extends CoreLibraryTypes { }
namespace Types {
export class TypeD { }
export class TypeE { }
export class TypeF { }
}
export { Types };
Недостатком, конечно, является то, что только при импорте второго модуля будут добавлены новые типы. Первый модуль останется прежним. В идеале было бы неплохо "обновить" пространство имен типов дополнительными типами (например, из плагинов), чтобы расширение модуля поддерживалось более естественным образом (вместо того, чтобы писать его вручную), но я думаю, что это нужно делать до кто-то понимает, что расширение модулей путем ручного объявления обновленных определений - это всего лишь пол-$ способ сделать то, что пространства имен уже делают (включая классы, как показано выше, которые уже могут использовать слияние пространства имен как часть класса). ;)
Примечание: в примере выше я использовал export { Types };
по причине - это позволит другим дополнить мои модули. Аугментация не поддерживается для экспорта по умолчанию (если это не нужно - сортируйте его практически).