打字稿:跨多个文件在同一命名空间中的可见性

时间:2018-09-20 16:53:13

标签: typescript namespaces

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

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

打字稿文档state that “即使文件是分开的,它们也可以构成同一个命名空间,并且可以像定义在一个文件中一样被使用”。 因此,我假设一个文件中的类可以访问同一名称空间中的另一个文件,即使它没有导出。 (因为如果在同一位置定义它们,情况将会如此)

但是,tsc抱怨找不到名称“ Dispatcher”。为什么会这样?此时我是否误解了文档?还是仅仅是编译器错误?如果是前者,那将是一个耻辱,因为仅名称空间的可见性将对单元测试和封装有很大帮助。

代码:

(为简单起见,更改了代码。如果出现语法错误,则是由该错误引起的):

Application.ts:

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

Dispatcher.ts:

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

1 个答案:

答案 0 :(得分:3)

  

Typescript文档指出:“即使文件是分开的,   它们每个都可以贡献给相同的名称空间,并且可以作为   如果它们都在一个定义中。”

这取决于“贡献给相同的名称空间”的精确定义。当前的解释是“任何导出的内容都可以在任何地方使用,任何没有导出的内容都只能在定义它的名称空间部分中使用”。 language specification对此进行了解释:

  

命名空间提供了一种组织代码和声明的机制。   命名容器的层次结构。命名空间已命名的成员   每个表示值,类型或名称空间或某种组合   其成员,这些成员可以是本地成员或出口成员。一个身体   命名空间对应于一次执行的函数,从而   提供有保证的地方状态维护机制   隔离。命名空间可以看作是   立即调用的函数表达(IIFE)模式。

如果存在相同名称空间的多个声明,则每个声明都被编译成一个单独的IIFE,如Dispatcher.ts的已编译javascript代码所示:

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

此行为在实现方面有意义。实现名称空间以使未导出的对象在所有名称空间实例之间共享但不能从外部访问是很麻烦的。