TypeScript 命名空间
随着代码的不断增加,我们需要有组织的组合代码。TypeScript在1.x版本中提供了命名空间的方式进行代码组织,这也是TypeScript官方代码的组织方式。同时,TypeScript还实现了JavaScript中流行的模块解决方案。
关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变化。 “内部模块”现在称做“命名空间”。 “外部模块”现在则简称为“模块”,这是为了与 ECMAScript 2015里的术语保持一致,(也就是说 module X {
相当于现在推荐的写法 namespace X {
)。
介绍
这篇文章描述了如何在TypeScript里使用命名空间(之前叫做“内部模块”)来组织你的代码。 就像我们在术语说明里提到的那样,“内部模块”现在叫做“命名空间”。 另外,任何使用 module
关键字来声明一个内部模块的地方都应该使用namespace
关键字来替换。 这就避免了让新的使用者被相似的名称所迷惑。
第一步
我们先来写一段程序并将在整篇文章中都使用这个例子。 我们定义几个简单的字符串验证器,假设你会使用它们来验证表单里的用户输入或验证外部数据。
所有的验证器都放在一个文件里
interface StringValidator {
isAcceptable(s: string): boolean;
} let lettersRegexp = /^[A-Za-z]+$/;
let 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
let strings = ["Hello", "98052", "101"]; // Validators to use
let validators: { [s: string]: StringValidator; } = {};
validators["ZIP code"] = new ZipCodeValidator();
validators["Letters only"] = new LettersOnlyValidator(); // Show whether each string passed each validator
for (let s of strings) {
for (let name in validators) {
let isMatch = validators[name].isAcceptable(s);
console.log(`'${ s }' ${ isMatch ? "matches" : "does not match" } '${ name }'.`);
}
}
命名空间
随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。 因此,我们把验证器包裹到一个命名空间内,而不是把它们放在全局命名空间下。
单文件命名空间
下面的例子里,把所有与验证器相关的类型都放到一个叫做Validation
的命名空间里叫做单文件命名空间。 因为我们想让这些接口和类在命名空间之外也是可访问的,所以需要使用 export
。 而变量 lettersRegexp
和numberRegexp
是实现的细节,不需要导出,因此它们在命名空间外是不能访问的。 在文件末尾的测试代码里,由于是在命名空间之外访问,因此需要限定类型的名称,比如 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
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 }`);
}
}
多文件命名空间
当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护,于是就有了多文件命名空间。
现在,我们把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
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 }`);
}
}
当涉及到多文件时,我们必须确保所有编译后的代码都被加载了。 加载代码有两种方式。
第一种方式,把所有的输入文件编译为一个输出文件,需要使用--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;
let 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 命名空间的更多相关文章
- typescript命名空间
/* 命名空间: 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数.类.接口等放置到命名空间内 同Java的包..Net的命名空间一样,TypeScript的命名空间可以将代码包裹 ...
- TypeScript入门八:TypeScript的命名空间
初识命名空间(namespace指令) 命名空间与文件拆分 多重命名空间与三斜杠指令引入依赖文件 一.初识命名空间(namespace指令) TypeScript的命名空间可以说就是ES6的模块化,其 ...
- 深入浅出 Typescript 学习笔记
TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准. TypeScript 由微软开发的自由和开源的编程语言. TypeScript 设计目标是开发大型应 ...
- TypeScript学习文档-基础篇(完结)
目录 TypeScript学习第一章:TypeScript初识 1.1 TypeScript学习初见 1.2 TypeScript介绍 1.3 JS .TS 和 ES之间的关系 1.4 TS的竞争者有 ...
- 转载:《TypeScript 中文入门教程》 6、命名空间
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...
- 转载:《TypeScript 中文入门教程》 5、命名空间和模块
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...
- TypeScript 素描 - 模块、命名空间
/* 其实前面一些都是废话,因为都和C#类似.从模块开始就需要深入的去理解了 文档反复声明了 内部模块现在称做 命令空间 外部模块称为 模块 模块在其自身的作用域里执行,而不是在全局作用域里,也就是说 ...
- TypeScript学习笔记(八):1.5版本之后的模块和命名空间
我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块 但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以 ...
- TypeScript学习笔记(七) - 命名空间
本篇将介绍TypeScript的命名空间,并简单说明一下与模块的区别. 在之前的例子里,有如下一段代码,通过修改这段代码来演示命名空间的用法. interface Animal { name: str ...
随机推荐
- [ZJOI2007][BZOJ1060]时态同步
Description 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数 字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路 ...
- [WEB安全]伪造IP地址进行爆破的BurpSuite插件:BurpFakeIP
0x01 简介 一个用于伪造ip地址进行爆破的BurpSuite插件,burpsuite伪造ip可用于突破waf及进行安全规则绕过等场景. 0x02 功能 伪造指定ip 伪造本地ip 伪造随机ip 随 ...
- 从一个表中往另外一个表中插入数据用到的SQL
insert into jdjc_zzjcxm (zj,jcxmmc) select sys_guid(),zbmc from JDJC_WHJXXMMC;
- docker run 参数含义
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项: -d: 后台运行容器,并返回容器ID: -i: 以交互模式运行容器,通常与 -t 同时使用: ...
- com.mysql.cj.jdbc.Driver 新特性jdbc.url连接供参考
com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6及以上版本中的参数详解: jdbc.url=jdbc:mysql://localhost:3306/t ...
- Bayesian Statistics for Genetics | 贝叶斯与遗传学
Common sense reduced to computation - Pierre-Simon, marquis de Laplace (1749–1827) Inventor of Bayes ...
- 图片旋转 1. cv2.getRotationMatrix2D(获得仿射变化矩阵) 2. cv2.warpAffine(进行仿射变化)
原文:https://www.cnblogs.com/my-love-is-python/p/10959612.html 1.rot_mat = cv2.getRotationMatrix2D(ce ...
- yii2 下的redis常用命令集合
<?php \Yii::$app->redis->set('user','aaa'); \Yii::$app->redis->set('user2','bbb'); \Y ...
- Android开发--IntentService的用法,你错过了什么
Android开发--IntentService的用法,你错过了什么 . 本文链接:https://blog.csdn.net/smbroe/article/details/45009721 Inte ...
- 邪淫真正的可怕危害 (转自学佛网:http://www.xuefo.net/nr/article54/544414.html)
邪淫真正的可怕危害 邪淫的害处可能很快就显现,也可能是逐渐的表现出来.但往往后者的害处更大.因为当积累了多年的邪淫果报一旦显现,后悔就已经晚了. 我本人就是一个很好的例子.回想自己这40多年的日子,邪 ...