Typescript:跨多个文件的同一命名空间内的可见性

Mat*_*ias 4 namespaces typescript

你能帮我吗 - 这是一个错误还是我误解了文档?

我的命名空间中有两个文件 - 您将在下面找到一个更简单的版本。

Typescript 文档指出 “尽管这些文件是独立的,但它们每个都可以贡献于同一名称空间,并且可以像它们全部定义在一个文件中一样使用”。因此,我假设一个文件中的类可以访问同一名称空间内的另一个文件,即使它没有导出。(因为如果它们定义在同一个地方就会出现这种情况)

然而,tsc 抱怨它找不到“Dispatcher”这个名字。为什么会出现这种情况?我现在误解了文档吗?或者这只是一个编译器错误?如果是前者,那就太可惜了,因为仅命名空间可见性对于单元测试和封装有很大帮助。

代码:

(为简单起见,更改了代码。如果存在语法错误,则它们是由此引起的):

应用程序.ts:

/// <reference path="Dispatcher.ts"/>
namespace Application {
    export class Application {
        constructor() {
            new Dispatcher(); 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

调度程序.ts:

namespace Application {
    class Dispatcher { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)

art*_*tem 6

Typescript 文档指出“尽管这些文件是独立的,但它们每个都可以贡献于相同的名称空间,并且可以像它们全部定义在一个文件中一样使用”。

这取决于“贡献于同一个命名空间”的精确定义。当前的解释是“导出的任何内容在任何地方都可用,未导出的任何内容仅在定义它的命名空间部分内可用”。语言规范中是这样解释的:

命名空间提供了一种在命名容器的层次结构中组织代码和声明的机制。命名空间具有命名成员,每个成员表示一个值、类型或命名空间或其某种组合,并且这些成员可以是本地的或导出的。命名空间的主体对应于执行一次的函数,从而提供了一种在确保隔离的情况下维护本地状态的机制。命名空间可以被认为是立即调用函数表达式 (IIFE) 模式的形式化。

如果同一命名空间有多个声明,则每个声明都会编译为单独的IIFE,如以下编译后的 javascript 代码所示Dispatcher.ts

var Application;
(function (Application) {
    class Dispatcher {
    }
})(Application || (Application = {}));
Run Code Online (Sandbox Code Playgroud)

结果是它的Dispatcher作用域位于函数内部,并且无法从外部访问。

即使您namespace Application在同一个文件中重复两次,每个文件都会定义自己的副本Dispatcher- 此代码不会出现错误:

namespace Application {
    class Dispatcher { /* ... */ }
}

namespace Application {
    class Dispatcher { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)

Dispatcher从外部访问的唯一方法namespace { ... }是将其导出。通过导出,Dispatcher成为对象的属性Application

namespace Application {
    export class Dispatcher { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)

编译后的代码:

var Application;
(function (Application) {
    class Dispatcher {
    }
    Application.Dispatcher = Dispatcher;
})(Application || (Application = {}));
Run Code Online (Sandbox Code Playgroud)

这种行为在实现方面是有意义的。实现命名空间以便未导出的对象在所有命名空间实例之间共享,但无法从外部访问是非常麻烦的。