版权

文章转载自:https://github.com/zhongsp

建议您直接跳转到上面的网址查看最新版本。

关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变化。 “内部模块”现在称做“命名空间”。 “外部模块”现在则简称为“模块”,这是为了与ECMAScript 2015里的术语保持一致,(也就是说 module X { 相当于现在推荐的写法 namespace X {)。

介绍

这篇文章描述了如何在TypeScript里使用命名空间(之前叫做“内部模块”)来组织你的代码。

就像我们在术语说明里提到的那样,“内部模块”现在叫做“命名空间”。

另外,任何使用module关键字来声明一个内部模块的地方都应该使用namespace关键字来替换。

这就避免了让新的使用者被相似的名称所迷惑。

第一步

我们先来写一段程序并将在整篇文章中都使用这个例子。 我们定义几个简单的字符串验证器,假设你会使用它们来验证表单里的用户输入或验证外部数据。

所有的验证器都放在一个文件里

interface StringValidator {
isAcceptable(s: string): boolean;
} var lettersRegexp = /^[A-Za-z]+$/;
var numberRegexp = /^[0-9]+$/; class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
} class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
} // Some samples to try
var strings = ["Hello", "98052", "101"];
// Validators to use
var validators: { [s: string]: StringValidator; } = {};
validators["ZIP code"] = new ZipCodeValidator();
validators["Letters only"] = new LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s => {
for (var name in validators) {
console.log(""" + s + "" " + (validators[name].isAcceptable(s) ? " matches " : " does not match ") + name);
}
});

命名空间

随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。 因此,我们把验证器包裹到一个命名空间内,而不是把它们放在全局命名空间下。

下面的例子里,把所有与验证器相关的类型都放到一个叫做Validation的命名空间里。 因为我们想让这些接口和类在命名空间之外也是可访问的,所以需要使用export。 相反的,变量lettersRegexpnumberRegexp是实现的细节,不需要导出,因此它们在命名空间外是不能访问的。 在文件末尾的测试代码里,由于是在命名空间之外访问,因此需要限定类型的名称,比如Validation.LettersOnlyValidator

使用命名空间的验证器

namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
} const lettersRegexp = /^[A-Za-z]+$/;
const numberRegexp = /^[0-9]+$/; export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
} export class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
} // Some samples to try
var strings = ["Hello", "98052", "101"];
// Validators to use
var validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s => {
for (var name in validators) {
console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`);
}
});

分离到多文件

当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护。

多文件中的命名空间

现在,我们把Validation命名空间分割成多个文件。 尽管是不同的文件,它们仍是同一个命名空间,并且在使用的时候就如同它们在一个文件中定义的一样。 因为不同文件之间存在依赖关系,所以我们加入了引用标签来告诉编译器文件之间的关联。 我们的测试代码保持不变。

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);
}
}
}
Test.ts
/// <reference path="Validation.ts" />
/// <reference path="LettersOnlyValidator.ts" />
/// <reference path="ZipCodeValidator.ts" /> // Some samples to try
var strings = ["Hello", "98052", "101"];
// Validators to use
var validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();
// Show whether each string passed each validator
strings.forEach(s => {
for (var name in validators) {
console.log(""" + s + "" " + (validators[name].isAcceptable(s) ? " matches " : " does not match ") + name);
}
});

当涉及到多文件时,我们必须确保所有编译后的代码都被加载了。 我们有两种方式。

第一种方式,把所有的输入文件编译为一个输出文件,需要使用--outFile标记:

tsc --outFile sample.js Test.ts

编译器会根据源码里的引用标签自动地对输出进行排序。你也可以单独地指定每个文件。

tsc --outFile sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts

第二种方式,我们可以编译每一个文件(默认方式),那么每个源文件都会对应生成一个JavaScript文件。 然后,在页面上通过<script>标签把所有生成的JavaScript文件按正确的顺序引进来,比如:

MyTestPage.html (excerpt)
    <script src="Validation.js" type="text/javascript" />
<script src="LettersOnlyValidator.js" type="text/javascript" />
<script src="ZipCodeValidator.js" type="text/javascript" />
<script src="Test.js" type="text/javascript" />

别名

另一种简化命名空间操作的方法是使用import q = x.y.z给常用的对象起一个短的名字。 不要与用来加载模块的import x = require('name')语法弄混了,这里的语法是为指定的符号创建一个别名。 你可以用这种方法为任意标识符创建别名,也包括导入的模块中的对象。

namespace Shapes {
export namespace Polygons {
export class Triangle { }
export class Square { }
}
} import polygons = Shapes.Polygons;
var sq = new polygons.Square(); // Same as "new Shapes.Polygons.Square()"

注意,我们并没有使用require关键字,而是直接使用导入符号的限定名赋值。 这与使用var相似,但它还适用于类型和导入的具有命名空间含义的符号。 重要的是,对于值来讲,import会生成与原始符号不同的引用,所以改变别名的var值并不会影响原始变量的值。

使用其它的JavaScript库

为了描述不是用TypeScript编写的类库的类型,我们需要声明类库导出的API。 由于大部分程序库只提供少数的顶级对象,命名空间是用来表示它们的一个好办法。

我们叫它声明因为它不是外部程序的具体实现。 我们通常在.d.ts里写这些定义。 如果你熟悉C/C++,你可以把它们当做.h文件。 让我们看一些例子。

外部命名空间

流行的程序库D3在全局对象d3里定义它的功能。 因为这个库通过一个<script>标签加载(不是通过模块加载器),它的声明文件使用内部模块来定义它的类型。 为了让TypeScript编译器识别它的类型,我们使用外部命名空间声明。 比如,我们可以像下面这样写:

D3.d.ts (部分摘录)
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
} export interface Event {
x: number;
y: number;
} export interface Base extends Selectors {
event: Event;
}
} declare var d3: D3.Base;

转载:《TypeScript 中文入门教程》 6、命名空间的更多相关文章

  1. 转载:TypeScript 简介与《TypeScript 中文入门教程》

    简介 TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程.安德斯·海尔斯伯格,C#的首席架构 ...

  2. 转载:《TypeScript 中文入门教程》

    缘由 事情是这样的,我想搜索 TypeScript 中文教程,结果在 https://www.baidu.com , https://cn.bing.com ,上都找不到官方的翻译,也没有一个像样的翻 ...

  3. 【转】TypeScript中文入门教程

    目录 虽然我是转载的,但看在Copy这么多文章也是很幸苦的好吧,我罗列一个目录. 转载:<TypeScript 中文入门教程> 17.注解 (2015-12-03 11:36) 转载:&l ...

  4. 《TypeScript 中文入门教程》

    转载:<TypeScript 中文入门教程> 17.注解 (2015-12-03 11:36) 转载:<TypeScript 中文入门教程> 16.Symbols (2015- ...

  5. 转载:《TypeScript 中文入门教程》 5、命名空间和模块

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...

  6. 转载:《TypeScript 中文入门教程》 14、输入.d.ts文件

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 当使用外部JavaScript库或新的宿主API时,你需要一个声明文件(.d.t ...

  7. 转载:《TypeScript 中文入门教程》 11、声明合并

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 TypeScript有一些独特的概念,有的是因为我们需要描述JavaScript ...

  8. 转载:《TypeScript 中文入门教程》 9、泛型

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性. 组件不 ...

  9. 转载:《TypeScript 中文入门教程》 8、函数

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 函数是JavaScript应用程序的基础. 它帮助你实现抽象层,模拟类,信息隐藏 ...

随机推荐

  1. 2013 duilib入门简明教程 -- 部分bug (11)

     一.WindowImplBase的bug     在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题,     1.最大化按钮的样式 ...

  2. 用SQL语句创建四个表并完成相关题目-10月18日更新

    1. 查询Student表中的所有记录的Sname.Ssex和Class列. 2. 查询教师所有的单位即不重复的Depart列. 3. 查询Student表的所有记录. 4. 查询Score表中成绩在 ...

  3. Distribution1:Distribution Reader

    在transactional replication中,在publication中执行了一个更新,例如:update table set col=? Where ?,如果table中含有大量的数据行, ...

  4. SSIS Design5:使用暂存

    以数据流的方式来设计Package,将核心数据处理移动到数据流中,一般情况下,能够减少临时表的创建,获得较高的处理性能,在某些情况下,使用暂存表(staging table)能够优化package设计 ...

  5. Sql Server系列:索引基础

    1 索引概念 索引用于快速查找在某个列中某个特定值的行,不使用索引,数据库必须从第1条记录开始读完整个表,知道找出需要的行.表越大,查询数据所花费的时间越多.如果表中查询的列有索引,数据库能快速到达一 ...

  6. jQuery 2.0.3 源码分析Sizzle引擎 - 编译函数(大篇幅)

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 从Sizzle1.8开始,这是Sizzle的分界线了,引入了编译函数机制 网上基本没有资料细说这个东东的,sizzle引入这 ...

  7. 【转】如何让你的Android SDK下载或者升级快如闪电

    准备学习Android开发,但是Android SDK Manager界面都刷不出来,今天看到了一篇文章,顿时就解决了,原文地址http://qichaochen.github.io/2014/12/ ...

  8. jQuery-easyui实现关闭全部tabs

    有时候当我们打开很多tabs选项卡时,要关闭它只能一个一个的进行关闭,显然太麻烦,这时可以在选项卡的最右边添加一个按钮 实现关闭全部. function openTab(text, url, icon ...

  9. 《ES6基础教程》之 Call 方法和 Apply 方法

    <script type="text/javascript"> // Call方法: // 语法:call(thisObj[,arg1,arg2,...,argN]) ...

  10. lintcode二叉树的锯齿形层次遍历 (双端队列)

    题目链接: http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出 ...