当前位置:网站首页>LayaBox---TypeScript---命名空间和模块
LayaBox---TypeScript---命名空间和模块
2022-08-02 10:01:00 【格拉格拉】
目录
1.介绍
我们先来写一段程序并将在整篇文章中都使用这个例子。
所有的验证器都放在一个文件里
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 }'.`);
}
}2.命名空间
随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。
2.1使用命名空间的验证器
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 }`);
}
}3.分离到多文件
当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护。
3.1 多文件的命名空间
现在,我们把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" />4.别名
另一种简化命名空间操作的方法是使用
import q = x.y.z给常用的对象起一个短的名字。 不要与用来加载模块的import x = require('name')语法弄混了,这里的语法是为指定的符号创建一个别名。 你可以用这种方法为任意标识符创建别名,也包括导入的模块中的对象。
namespace Shapes {
export namespace Polygons {
export class Triangle { }
export class Square { }
}
}
import polygons = Shapes.Polygons;
// Same as "new Shapes.Polygons.Square()"
let sq = new polygons.Square();️注意:
1.我们并没有使用
require关键字,而是直接使用导入符号的限定名赋值。2.这与使用
var相似,但它还适用于类型和导入的具有命名空间含义的符号。3.重要的是,对于值来讲,
import会生成与原始符号不同的引用,所以改变别名的var值并不会影响原始变量的值。
5.使用其它的JavaScript库
5.1 外部明明空间
流行的程序库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;6.命名空间和模块
命名空间是位于全局命名空间下的一个普通的带有名字的JavaScript对象。
它们可以在多文件中同时使用,并通过
--outFile结合在一起。 命名空间是帮你组织Web应用不错的方式,你可以把所有依赖都放在HTML页面的<script>标签里。
模块像命名空间一样,可以包含代码和声明。 不同的是模块可以 声明它的依赖。
模块会把依赖添加到模块加载器上(例如CommonJs / Require.js)。模块也提供了更好的代码重用,更强的封闭性以及更好的使用工具进行优化。
7. 命名空间和模块的陷阱
7.1 对模块使用
一个常见的错误是使用/// <reference>引用模块文件,应该使用import。 要理解这之间的区别,我们首先应该弄清编译器是如何根据 import路径(例如,import x from "...";或import x = require("...")里面的...,等等)来定位模块的类型信息的。
编译器首先尝试去查找相应路径下的.ts,.tsx再或者.d.ts。 如果这些文件都找不到,编译器会查找 外部模块声明。 回想一下,它们是在 .d.ts文件里声明的。
------------------------myModules.d.ts---------------------
// In a .d.ts file or .ts file that is not a module:
declare module "SomeModule" {
export function fn(): string;
}
//----------myOtherModule.ts---------------------------------
/// <reference path="myModules.d.ts" />
import * as m from "SomeModule";这里的引用标签指定了外来模块的位置。 这就是一些TypeScript例子中引用 node.d.ts的方法。
7.2 不必要的命名空间
如果你想把命名空间转换为模块,它可能会像下面这个文件一件:
---------------shapes.ts--------------------------------------------
export namespace Shapes {
export class Triangle { /* ... */ }
export class Square { /* ... */ }
}
顶层的模块Shapes包裹了Triangle和Square。 对于使用它的人来说这是令人迷惑和讨厌的:
--------------shapeConsumer.ts-------------------------------------
import * as shapes from "./shapes";
let t = new shapes.Shapes.Triangle(); // shapes.Shapes?不应该对模块使用命名空间,使用命名空间是为了提供逻辑分组和避免命名冲突。 模块文件本身已经是一个逻辑分组,并且它的名字是由导入这个模块的代码指定,所以没有必要为导出的对象增加额外的模块层。
下面是改进的例子:
------------shapes.ts--------------------------
export class Triangle { /* ... */ }
export class Square { /* ... */ }
---------shapeConsumer.ts----------------------
import * as shapes from "./shapes";
let t = new shapes.Triangle();7.3 模块的取舍
就像每个JS文件对应一个模块一样,TypeScript里模块文件与生成的JS文件也是一一对应的。 这会产生一种影响,根据你指定的目标模块系统的不同,你可能无法连接多个模块源文件。 例如当目标模块系统为 commonjs或umd时,无法使用outFile选项,但是在TypeScript 1.8以上的版本能够使用outFile当目标为amd或system。
边栏推荐
- 李航《统计学习方法》笔记之感知机perceptron
- Do you agree with this view?Most businesses are digitizing just to ease anxiety
- 一款优秀的中文识别库——ocr
- 转转反爬攻防战
- R语言使用zoo包中的rollapply函数以滚动的方式、窗口移动的方式将指定函数应用于时间序列、设置align参数指定结果数据中的时间标签取自窗口中的位置(参数right指定取自窗口的最右侧)
- 新“内卷”席卷科技圈,Google CEO 要求 174000 员工提高工作效率!
- R语言ggpubr包的ggbarplot函数可视化分组柱状图、设置add参数为mean_se可视化不同水平均值的柱状图并为柱状图添加误差线(se标准误差)、position参数自定义分组柱状图分离
- Pytorch的LSTM参数解释
- 牛客刷题——剑指offer(第三期)
- 软件测试与质量 之白盒测试
猜你喜欢

享年94岁,图灵奖得主、计算复杂性理论先驱Juris Hartmanis逝世

QT专题:组合会话框和文本编辑器

新“内卷”席卷科技圈,Google CEO 要求 174000 员工提高工作效率!

Shell脚本实现多选DNS同时批量解析域名IP地址(新更新)

Application scenarios of js anti-shake function and function throttling

李航《统计学习方法》笔记之k近邻法

HikariCP数据库连接池,太快了!

The k-nearest neighbor method in the notes of Li Hang's "Statistical Learning Methods"

The heavyweights are coming!Spoilers for the highlights of the Alibaba Cloud Life Science and Intelligent Computing Summit

【新版干货书】深度伪造 (DeepFakes):创造,检测和影响
随机推荐
yolov7 innovation point
Linux系统卸载,安装,升级,迁移clickHouse数据库
适配器模式适配出栈和队列及优先级队列
使用scrapy 把爬到的数据保存到mysql 防止重复
npm ERR! 400 Bad Request - PUT xxx - Cannot publish over previously published version “1.0.0“.
Linux system uninstall, install, upgrade, migrate clickHouse database
二维数组零碎知识梳理
食品安全 | 鱼肝油不是鱼油,家有宝宝的注意了
打印lua内部结构的函数调用
用汇编实现爱心特效【七夕来袭】
李航《统计学习方法》笔记之感知机perceptron
sqlmap安装教程用w+r打开(sqlyog安装步骤)
鸿星尔克再捐一个亿
云原生应用平台的核心模块有哪些
HikariCP数据库连接池,太快了!
In the whole development of chi V853 board tried to compile QT test
零代码工具推荐---HiFlow
C语言volatile关键字、内嵌汇编volatile与编译器的爱恨情仇
软件测试之发现和解决bug
利用二维数据学习纹理三维网格生成(CVPR 2020)