随着 ES6 模块化的广泛使用,现在已不建议使用 TypeScript 的命名空间
namespace
作为组织代码的方式,而是推荐使用 ES6 的模块化方案。现在命名空间主要用在声明文件中。
随着一个模块中代码的增加,需要将代码分离到不同的文件中以便于维护。此时可以使用命名空间 namespace
,同一个命名空间中的代码使用起来就像是在同一个文件中。但是这些分散的文件可能存在存在依赖关系,所以需要加入引用标签(三斜线指令)来关联这些文件:
Validation.ts
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean
}
}
LettersOnlyValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s)
}
}
}
ZipCodeValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
const numberRegexp = /^[0-9]+$/
export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s)
}
}
}
如上面代码所示,同一个 Validation
命名空间里的代码,如果有依赖关系,可以使用三斜线指令来声明,需要暴露到命名空间之外可以使用 export
。
外部代码调用命名空间内的代码时,需要使用三斜线指令声明引用的文件,并且需要加上命名空间(如: Validation.StringValidator
)来访问其中的代码:
/// <reference path="Validation.ts" />
/// <reference path="LettersOnlyValidator.ts" />
/// <reference path="ZipCodeValidator.ts" />
// Some samples to try
let strings = ["Hello", "98052", "101"];
// Validators to use
let validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
for (let s of strings) {
for (let name in validators) {
console.log(""" + s + "" " + (validators[name].isAcceptable(s) ? " matches " : " does not match ") + name);
}
}
当使用命名空间分离代码之后,要确保加载了所有的代码:
第一种方式,把所有文件编译成一个文件:
tsc --outFile build.js Test.ts
第二种方式(默认方式),为每个文件生成 js 文件,然后按正确顺序手动使用 <script>
引入页面。
为了简化对命名空间中的变量的引用,可以使用 import q = x.y.z
给常用的对象起一个短的别名:
namespace Shapes {
export namespace Polygons {
export class Triangle {}
export class Square {}
}
}
import polygons = Shapes.Polygons
let sq = new polygons.Square() // Same as "new Shapes.Polygons.Square()"
注意:该语法不是
import module = require('module')
。
命名空间很难识别组件间的依赖关系,需要手动确认引入顺序,而模块没有这些问题,从 ES6 开始,模块是默认并推荐的代码组织方式。