使用命名空间组织TypeScript代码
引言
随着企业软件中第三方库的使用越来越多,我们经常遇到全局命名空间被污染的问题,导致全局命名空间中的组件之间发生名称冲突。因此,我们需要使用命名空间来组织代码块,以便使变量、对象和类得到唯一的识别。
在这篇文章中,我们将讨论命名空间,何时需要它们,以及如何使用它们来增强TypeScript代码的组织。
前提条件
- 对TypeScript的了解
- 熟悉JavaScript
什么是命名空间?
命名空间是组织代码的范式,使变量、函数、接口或类在本地范围内被分组,以避免全局范围内的组件之间的命名冲突。这是减少全局范围污染的最常见的策略之一。
虽然模块也被用于代码组织,但命名空间很容易用于简单的实现。模块提供了一些额外的好处,如强大的代码隔离、对捆绑的强大支持、组件的重新输出以及组件的重命名,而这些是命名空间所不具备的。
为什么我们需要命名空间?
命名空间有这些优点。
- 代码重用性 - 命名空间对代码重用性的重要性是不可低估的
- 臃肿的全局范围 - 命名空间减少了全局范围内的代码量,使其不那么臃肿
- 第三方库 - 随着越来越多的网站依赖于第三方库,使用命名空间来保护你的代码以防止你的代码和第三方库之间的同名冲突非常重要。
- 分布式开发 - 随着分布式开发的流行,污染几乎是不可避免的,因为开发人员更容易使用共同的变量或类名。这就导致了名称冲突和全局范围的污染。
使用命名空间的设计考虑
隐式依赖关系的顺序
在与一些外部库合作时使用命名空间将需要在你的代码和这些库之间隐式实现依赖关系。这就导致了自己管理依赖关系的压力,以便正确地加载它们,因为依赖关系可能是容易出错的。
如果你发现自己处于这种情况,使用模块将为你节省压力。
Node.js应用程序
对于Node.js应用程序,推荐使用模块而不是命名空间,因为模块是Node中封装和代码组织的事实上的标准。
非JavaScript内容的导入
在处理非JavaScript内容时,推荐使用模块而不是命名空间,因为一些模块加载器(如SystemJS和AMD)允许导入非JavaScript内容。
遗留代码
当处理一个不再被设计但不断被修补的代码库时,建议使用命名空间而不是模块。
另外,命名空间在移植旧的JavaScript代码时也很方便。
探索TypeScript中的命名空间
现在我们对TypeScript命名空间是什么以及为什么需要它们有了共同的理解,我们可以更深入地探讨如何使用它们。
鉴于TypeScript是JavaScript的超集,它的命名空间概念来源于JavaScript。
默认情况下,JavaScript没有关于命名空间的规定,因为我们必须使用IIFE(Immediately Invoked Function Expression)实现命名空间。
var Vehicle;
(function (Vehicle) {
let name = "car";
})(Vehicle || (Vehicle = {}));
这对于定义一个命名空间来说,有太多的代码了。同时,TypeScript的做法是不同的。
单一文件的命名空间
在TypeScript中,命名空间的定义是使用namespace
关键字,后面跟一个自选的名字。
一个单一的TypeScript文件可以根据需要拥有许多命名空间。
namespace Vehicle {}
namespace Animal {}
正如我们所看到的,TypeScript的命名空间与我们使用IIFE实现命名空间的JavaScript相比,是一块语法蛋糕。
函数、变量和类可以在命名空间内定义,如下所示。
namespace Vehicle {
const name = "Toyota"
function getName () {
return `${name}`
}
}
namespace Animal {
const name = "Panda"
function getName () {
return `${name}`
}
}
上面的代码允许我们使用相同的变量和函数名称而不发生碰撞。
访问命名空间外的函数、变量、对象和类
为了在命名空间之外访问函数或类,必须在函数或类的名称之前添加export
关键字,如下所示。
namespace Vehicle {
const name = "Toyota"
export function getName () {
return `${name}`
}
}
注意,我们必须省略变量的export
关键字,因为它不应该在名字空间之外被访问。
现在,我们可以访问getName
函数,如下所示。
Vehicle.getName() //Toyota
使用嵌套命名空间组织代码
TypeScript允许我们使用嵌套命名空间来组织我们的代码。
我们可以创建嵌套的名字空间,如下所示。
namespace TransportMeans {
export namespace Vehicle {
const name = "Toyota"
export function getName () {
return `${name}`
}
}
}
注意在Vehicle
命名空间之前的export
关键字。这允许命名空间在TransportMeans
命名空间之外被访问。
我们还可以进行命名空间的深度嵌套。
我们的嵌套命名空间可以被访问,如下所示。
TransporMeans.Vehicle.getName() // Toyota
命名空间的别名
对于深度嵌套的命名空间,命名空间别名可以派上用场,使事情保持干净。
命名空间别名是使用import关键字定义的,如下所示。
import carName= TransporMeans.Vehicle;
carName.getName(); //Toyota
多文件命名间距
命名空间可以在多个TypeScript文件中共享。这是由reference
标签实现的。
考虑到以下情况。
//constant.ts
export const name = "Toyota"
//vehicle.ts
<reference path = "constant.ts" />
export namespace Vehicle {
export function getName () {
return `${name}`
}
}
在这里,我们不得不引用constant.ts
文件,以便访问name
。
//index.ts
<reference path = "constant.ts" />
<reference path = "vehicle.ts" />
Vehicle.getName() // Toyota
注意我们是如何从最高级别的命名空间开始引用的。这就是如何处理多文件接口中的引用。TypeScript在编译文件的时候会使用这个顺序。
我们可以通过以下命令指示编译器将我们的多文件TypeScript代码编译成一个单一的JavaScript文件。
tsc --outFile index.js index.ts
通过这个命令,TypeScript编译器将产生一个名为index.js
的单一JavaScript文件。
结论
为了构建可扩展和可重用的TypeScript应用程序,TypeScript命名空间很方便,因为它们可以改善我们应用程序的组织和结构。
在这篇文章中,我们已经能够探索命名空间,何时需要它们,以及如何实现它们。请查看TypeScript手册。命名空间,了解更多关于命名空间的信息。
The postOrganizing TypeScript code using namespacesappeared first onLogRocket Blog.
转载自:https://juejin.cn/post/7062664731135311909