如何在TypeScript中声明一个模块
模块是可以在另一个代码中调用或使用的一段代码。在TypeScript中,模块并不是什么新东西。模块的概念是由JavaScript在ECMAScript 2015发布时引入的。TypeScript只是再次使用了这个特性。
如果没有模块,代码会失效吗?
当然不会。代码仍然可以工作。但是,没有模块化的代码存在着一些主要的缺陷。
假设我们创建了一个非常基本的聊天应用程序,可以发送或接收文本消息。最初,我们将整个代码添加到了2-3个文件中,应用程序运行良好。后来,我们决定添加一个功能,可以录制和发送音频消息。为此,我们又在相同的文件中添加了更多的代码,应用程序仍然良好运行。后来,我们决定添加像分享图片、分享视频或者一些大文件之类的功能,我们继续把代码添加到相同的文件,或者添加到1-2个额外的文件中。现在出现了一个问题。以下是我们可以预见到的一些问题:
- 应用程序将开始变得缓慢(或在某一点上变得非常缓慢)。
- 应用程序频繁崩溃,可能导致数据丢失。
- 代码库将变得杂乱无章(无法维护)。
- 故障修复或调试是另一个大问题。
- 对测试团队来说是一场噩梦。
所有以上问题(以及更多)都可以通过使我们的代码更模块化来解决。
在不使用模块的情况下进行开发: 让我们模拟一种情景。我们想买一些水果,比如苹果、猕猴桃和草莓。我们将为所有这三种水果分别创建3个单独的类。由于这三种水果都是水果,所以它们共享一些共同的特征,比如名称、颜色和数量。因此,我们将创建另一个类(作为数据类型)并具有一个方法。让我们逐个创建这些类。
1. 创建苹果类: 右键点击项目文件夹,然后点击“新建文件”。称为apple.ts。首先,我们在这里定义水果类,以便用于苹果,并且在同一个文件中,我们还会定义苹果类:
Javascript
class Fruit {
// Properties that every fruits have
name: string;
color: string;
quantity: number;
// To initialize the values
constructor(name, color, quantity) {
// Initialize values using this operator
}
myCart() {
// A simple placeholder text
console.log("I have " + this.quantity +
" " + this.color + " " + this.name +
" in my cart");
}
}
class Apple {
// Initialize Fruits class with values
fruits: Fruits = new Fruits(..., ..., ...);
constructor() {
// call method to see everything is correct
this.fruits.myCart();
}
}
// initialize apple class and call
// its constructor automatically
var obj: Apple = new Apple();
我们将对Kiwi类型做相同的过程
2. 创建Kiwi类: 右键单击项目文件夹,然后点击“新建文件”。将其命名为kiwi.ts。 首先,我们将在这里定义Fruit类,用作kiwi的数据类型,并且在同一个文件中,我们还将定义Kiwi类:
JavaScript
class Fruit {
// Properties that every fruits have
name: string;
color: string;
quantity: number;
// Initialize the values
constructor(name, color, quantity) {
// Initialize values using this operator
}
myCart() {
// A simple placeholder text
console.log("I have " + this.quantity +
" " + this.color + " " + this.name +
" in my cart");
}
}
class Kiwi {
// Initialize Fruits class with values
fruits: Fruits = new Fruits(..., ..., ...);
constructor() {
// Call method to see everything is correct
this.fruits.myCart();
}
}
// Initialize kiwi class and
// call its constructor automatically
var obj: Kiwi = new Kiwi();
3. 创建Strawberry类: 右键点击项目文件夹,然后点击“新建文件”。将其命名为strawberry.ts。 首先,在这里我们将定义用作strawberry的数据类型的Fruit类,然后在同一文件中我们还将定义Strawberry类:
Javascript
class Fruit {
// Properties that every fruits have
name: string;
color: string;
quantity: number;
// Initialize the values
constructor(name, color, quantity) {
// Initialize values using this operator
}
myCart() {
// A simple placeholder text
console.log("I have " + this.quantity +
" " + this.color + " " + this.name +
" in my cart");
}
}
class Strawberry {
// Initialize Fruits class with values
fruits: Fruits = new Fruits(..., ..., ...);
constructor() {
// Call method to see everything is correct
this.fruits.myCart();
}
}
// Initialize strawberry class and
// call its constructor automatically
var obj: Strawberry = new Strawberry();
使用模块化方法减少开发工作量: 上述方法存在一个严重缺陷。没错,你说得对。一次又一次重新定义相同的Fruits类是非常愚蠢的。这就是模块的用武之地。如果我们将Fruits类放在一个文件中,并将其称为一个模块,然后只需要在需要的地方调用该类/模块。这将节省开发人员大量的时间和精力。让我们快速完成这个步骤。
步骤1: 创建一个名为Fruits.ts的新文件
步骤2: 从所有3个类中删除Fruits类的定义
步骤3: 只将它粘贴到一个位置,即文件Fruits.ts中
JavaScript
export class Fruit {
// Properties that every fruits have
name: string;
color: string;
quantity: number;
// Initialize the values
constructor(name, color, quantity) {
// Initialize values using this operator
}
myCart() {
// A simple placeholder text
console.log("I have " + this.quantity +
" " + this.color + " " + this.name +
" in my cart");
}
}
console.log("Hello world!");
注意我们首先使用了export关键字。export关键字实际上使得我们的类(或接口)可以在项目的其他地方使用。同时,我们在希望使用导出的模块的模块中使用import语句。
还要注意我们在文件末尾添加了一个console log语句。这并非必需,但我们想在本文中稍后告诉您一个重要的事实。现在,您可以忽略它,并假设它不存在。
现在我们的模块准备好了。我们可以在我们的类中调用它。从技术上讲,我们称之为“导入”,并使用一个关键字叫做“import”。
语法:
import {classname} from './location';
让我们快速导入相同的文件:
文件名:Apple.ts
Javascript
import { Fruits } from './main';
class Apple {
fruits: Fruits = new Fruits('apples', 'green', 5);
constructor() {
this.fruits.myCart();
}
}
var obj: Apple = new Apple();
文件名:Kiwi.ts
Javascript
import { Fruits } from './main';
class Kiwi {
fruits: Fruits = new Fruits('kiwi', 'golden', 2);
constructor() {
this.fruits.myCart();
}
}
var obj: Kiwi = new Kiwi();
文件名:Strawberry.ts
Javascript
import { Fruits } from './main';
class Strawberry {
fruits: Fruits = new Fruits('strawberries', 'red', 5);
constructor() {
this.fruits.myCart();
}
}
var obj: Strawberry = new Strawberry();
看看它现在是多么干净。现在它易于理解和维护。这就是模块化方法背后的整体理念。
留下的一些要点: 我们在最后添加了一个console语句。原因如下。让我先给你展示一下输出结果。

每次我们运行这些文件时,我们得到的是一个特定类的输出,但同时我们也得到了“Hello world!”的输出。
原因是它不属于导出类。那为什么会被调用呢?原因是每当我们导入一个模块时,整个模块会被作为一个简单程序执行一次,文件中的每一行都会被执行,无论它是否在导出类的大括号内。所以要小心在里面放什么。根据专家的意见,不应该有多余的代码行。如果不需要,可以将其放在某个方法中,或者删除这些语句。
总结: 所以,模块实际上是一个概念或方法,将一段代码分开并显式地导出,以便其他代码片段可以导入它。我们使用export关键字将一个类公开,使用import来使用已导出的模块。
如何执行代码:
首先我们将运行:
tsc apple.ts
然后我们将运行:
node apple.js
这样做是因为并非所有浏览器都像理解JavaScript一样理解TypeScript。因此,TypeScript首先必须编译为JavaScript,因此我们使用node命令进行编译。我们也可以使用AND运算符将两个命令组合在一起:
对于Linux:
tsc apple.ts && node apple.js
对于Windows,我可以使用管道运算符:
tsc apple.ts | node apple.js
同样,我可以运行Kiwi和Strawberry类。
最终输出:

最后提醒:
这是编写代码的专业方式,被全球广泛遵循。所以,如果明天你在编写代码或者审查别人的代码时,请特别注意代码的模块化。这会让你的生活更轻松。
极客教程