В документации Typescript говорится, что «Несмотря на то, что файлы являются отдельными, каждый из них может вносить свой вклад в одно и то же пространство имен и может использоваться, как если бы они все были определены в одном».
Это зависит от точного определения «внести вклад в то же пространство имен».В настоящее время интерпретация такова: «все, что экспортируется, доступно везде, все, что не экспортировано, доступно только внутри той части пространства имен, где это определено».Вот как это объясняется в спецификации языка :
Пространства имен обеспечивают механизм для организации кода и объявлений в иерархиях именованных контейнеров.Пространства имен имеют именованные члены, каждое из которых обозначает значение, тип или пространство имен или некоторую их комбинацию, и эти члены могут быть локальными или экспортированными.Тело пространства имен соответствует функции, которая выполняется один раз, тем самым обеспечивая механизм для поддержания локального состояния с гарантированной изоляцией.Пространства имен можно рассматривать как формализацию шаблона выражения немедленного вызова функции (IIFE).
Если существует несколько объявлений одного и того же пространства имен, каждое из них компилируется в отдельный IIFE., как видно из скомпилированного кода javascript для Dispatcher.ts
:
var Application;
(function (Application) {
class Dispatcher {
}
})(Application || (Application = {}));
В результате область действия Dispatcher
находится внутри функции и недоступна извне.
Даже если вы дважды повторили namespace Application
в одном и том же файле, каждый из них определил бы свою собственную копию Dispatcher
- для этого кода нет ошибки:
namespace Application {
class Dispatcher { /* ... */ }
}
namespace Application {
class Dispatcher { /* ... */ }
}
единственный способ сделать Dispatcher
доступным извне namespace { ... }
- это экспортировать его.При экспорте Dispatcher
становится свойством Application
объекта:
namespace Application {
export class Dispatcher { /* ... */ }
}
скомпилированного кода:
var Application;
(function (Application) {
class Dispatcher {
}
Application.Dispatcher = Dispatcher;
})(Application || (Application = {}));
Это поведение имеет смысл с точки зрения реализации.Было бы очень сложно реализовать пространство имен, чтобы неэкспортированные объекты были общими для всех экземпляров пространства имен, но не были доступны извне.