TypeScript由微软构建,旨在帮助开发人员更轻松地构建大型前端应用程序。它是JavaScript的超集,为它带来了丰富的类型系统,这种类型系统可以帮助开发人员更早的发现错误,并允许可靠地创建工具浏览和重构代码。
目录
Type |
Description |
string |
表示Unicode字符序列。 |
number |
表示整数和浮点数。 |
boolean |
表示true或false。 |
undefined |
表示一个尚未初始化的值。 |
null |
表示没有值。 |
Key word |
Description |
Any |
|
Void |
|
Never |
|
Enum |
|
Object |
|
Array |
|
接口是一种契约,它定义了带有属性和方法定义的集合的类型,而没有任何实现。JavaScript中不存在接口,因此TypeScript编译器仅适用它们通过类型检查来实施契约。
我们使用interface关键字创建一个接口,其后是接口名称,然后是用花括号组成的内容。
Interface Project{
……..
}
类具有许多编程语言的功能,包括JavaScript。它们使我们能够以接口与类型别名类似的方式对带有类型注释的对象进行使用。然后,类具有比接口和类型别名更多的功能。
Class Project{
…..
}
默认情况下,TypeScript生成的JavaScript代码在全局范围内执行。这意味着一个文件中代码将自动在另一个文件中可以使用。然而,这意味着如果名称相同,我们实现的功能可以覆盖其他文件中的功能,这将导致我们的应用程序会中段,即运行失败。
在全局范围内操作存在问题,因为项目名称可能会在不同的文件直接发生冲突,并且随着我们的代码库的增长,这很难避免。模块解决了这个问题,并帮助我们编写了组织良好且可重用的代码。
JavaScript中的模块功能是ES6的一部分。但是,在此标准化之前,其他流行的模块格式中也存在许多代码。TypeScript允许我们使用ES6模块编写代码,然后可以将其转换为另一种模块格式。
以下是TypeScript可以转换为不同模块格式的简要说明:
AMD(Asynchronous Module Definition):这通常在针对浏览器的代码中使用,并使用define函数定义模块。
CommonJS:Node.js程序中使用此格式。其使用module.exports定义模块并需要定义依赖项。
UMD(Universal Module Definition):这可以在浏览器应用程序和Node.js应用程序中使用。
ES6:这是本机JavaScript模块格式,使用export关键字定义模块并使用import定义依赖项。
从模块中导出的代码可以被其他模块使用。为了从模块中导出代码,我们使用export关键字。我们可以指定在定义项目之前直接使用export导出接口,别名,函数,常量等。
导入可以使我们从导出的模块中导入代码。我们使用导入语句来执行此操作,该语句包括要使用大括号导入的项目名称和从中获取项目的文件路径(不包括ts扩展名)。我们只能导入在其他模块文件中导出的项目。
我们可以指定一个默认情况下使用default关键字导出的项目:
Export default interface{
Name:string;
unitPrice:number;
}
注意,我们不需要命名接口,然后可以导入默认导出的项目,而无需使用花括号来选择我们所需要的名称。
Import poduct from “./product”;
我们需要先编译我们的TypeScript代码,然后才能在浏览器中执行。为此,我们在要编译的文件上运行TypeSctipttsc。
TypeScript很流行,可以应用许多不同的情况:
所有这些情况对TypeScript编译器的要求都稍有不同。所以,编译器为我们提供了不同的选项,以满足我们对特定情况的要求。
所有的编译配置都可以在https://www.typescriptlang.org/docs/handbook/compiler-options.html中找到。
以下列出经常使用的一些配置选项:
这确定了将在其中生成编译代码的ECMAScript版本。默认值是ES3,它将确保代码可以在各种浏览器使用的不同版本。但是,此编译目标将生成最多的代码,因为编译器将为ES3中不支持的功能生成polyfill代码。ESNext选项是另一个极端,它可以编译为最新支持的建议ES功能。这将生成最少的代码,但仅在浏览器上有效实现了我们所使用的功能。
作为例子:tsc orderDetail –target es6
默认情况下,已转译的JavaScript文件与TypeScript文件位于同一个目录中。--outDir可用于将这些文件放置在其他目录中。
让我们尝试一下,然后将转译的orderDetail.js输出到名为dist的文件夹中。
让我们在终端中输入一下内容:
Tsc orderDetail –outDir dist
将创建一个dist文件夹,其中包含生成的orderDetail.js文件。
这指定了生成的JavaScript应该使用的模块格式。默认实以ES3或ES5为目标的CommonJS模块格式。目前,在创建新项目时,ES6和ESNext是常用选项。
此选项告诉TypeScript编译器处理JavaScript文件以及TypeScript文件。如果我们已经用JavaScript编写了一些代码并且使用了尚未在所有浏览器中实现的功能,这将非常有用。这种情况下,我们可以使用TypeScript编译器将JavaScript转换为可以在广泛的浏览器中使用的代码。
此选项使TypeScript编译器无限期运行。每当更改源文件时,都会自动触发编译过程以生成新版本。这是在开发过程中开启的有用选项:
tsc orderDetail --watch
GetTotal(discount:number):number{
}
要退出监视模式,我们可以通过单击终端的bin图表来终止终端。
这强制我们明确指定要使用它的任何类型,同时也强制我们考虑使用任何一种类型以及是否真的需要它。
让我们看下下面的例子:
Export class OrderDetail{
doSomething(input){
}
}
Tsc orderDetail –noImplicitAny
编译器输出一下错误信息,因为我们没有明确说明输入参数的类型:
orderDetail.ts(14,15): error TS7006: Parameter 'input' implicitly has an 'any' type.
Export class OrderDetail{
doSomething(input:number){
}
}
如果我们再次使用—noImplicitAny进行编译,则编译顺利通过。
如果返回类型不是void,这可以确保我们在函数的所有分支中返回值。
如下所示:
getTotal(discount:number):number{
if (discount){
return 0.5 * discount;
}else{
//we forgot about this branch!
}
}
Tsc orderDetail
Tsc orderDetail --noImplicitReturns
正如预期的那样,我们收到以下错误。
orderDetail.ts(9,31): error TS7030: Not all code paths return a value.
如果设置此选项,在编译过程中会生成*.map文件。这将使我们能够调试程序的TypeScript版本(而不是转译的JavaScript)。因此,通常在开发过程中将其打开。
这告诉TypeScript编译器如何解析模块。这可以将其设置为classic或者node。如果使用的是ES6模块,则默认为classic,这意味着TypeScript编译器很难找到第三方软件包,例如Axios,因此,我们可以显示设置到节点,以告诉编译器在“node_modules”中查找模块。
正如我们所看到的,我们可以将许多不同的开关应用于编译过程,并且在命令行上重复指定这些开关有些笨拙。幸运的是,我们可以在名为tsconfig.json的文件中指定这些选项。我们拥有的编译器选项在上一节中介绍的内容是在没有”—“前缀的compileOptions字段中定义的。
如下所示:
让我们创建一个具有以下内容的tsconfig.json文件:
{
"compilerOptions": {
"target": "esnext",
"outDir": "dist",
"module": "es6",
"moduleResolution": "node",
"sourceMap": true,
"noImplicitReturns": true,
"noImplicitAny": true
}
}
2. 让我们运行编译而不指定源文件和任何标志。
tsc
编译将运行良好,将已编译的JavaScript与源映射文件一起输出到dist文件夹。
有几种方法可以告诉TypeScript编译器处理那些文件。最简单的方法是在”文件”字段中明确列出文件:
{
“compilerOptions”:{
….
}
“files”:[“product.ts”,”orderDetail.ts”]
}
但是,随着代码库的增长,这种方法很难维护。一种更易于维护的方法是使用include和exclude字段定义需要包含和排除的文件模式。
下面的实例查看这些字段的具体用法:
{
“compilerOptions”:{
….
}
“include”:[“src/**/*”]
}
tsc
让我们创建一个src文件夹并将orderDetail.ts移到该文件夹中。如果再次进行编译,它将成功找到文件并进行编译。
因此,我们有很多选择可以使TypeScript编译器适应我们的特定情况。
一些选项(例如--noImplicitAny)强制我们编写良好的TypeScript代码。通过将linting引入我们的项目中,我们可以将代码检查提高到一个新的水平。
如我们所见,编译器对我们的TypeScript代码进行了许多有用的检查,以帮助我们编写无错误的代码。我们可以更进一步,使代码更加整洁,以帮助我们使代码更具有可读性和可维护性。TSLint是在TypeScript项目中非常流行的linter。
TSLint的主页位于https://palantir.github.io/tslint/
安装TSLint以及一个Visual Studio Code扩展,它将在代码中突出显示出有问题的代码。
Npm install –g tslint
已经安装了此扩展程序以及全局范围内的STLint,则将在我们的代码中突出显示代码错误。
Tslint在检查代码时使用的规则可言在名为tslint.json的文件中进行配置。为了使用这些规则,首先需要个TypeScript文件。
成员访问规则强制我们明确声明访问类的修饰符。我们尚未在OrderDetail类中显示定义属性和方法访问修饰符,因为默认情况下它们使公共的,因此,有了插入规则,Visual Studio Code将向我们强调缺少访问修饰符:
成员访问规则强制我们编写更多代码,这怎么可能是一件好事?如果你正在阅读代码并且对TypeScript的了解不够深,以至于没有访问修饰符的类成员是公共的,该规则很有用。因此,如果团队由不太了解TypeScript的开发人员组成,则很适用。但是,不一定适合经验丰富的TypeScript开发人员团队。许多的tslint规则例如member-access,它们会运作良好,而在其他团队中,它们并没有真正增加价值,这就是为什么规则是可配置的。
Tslint拥有一组方便使用的内置规则。我们可以通过在extends字段中指定规则集名称来使用它们。我们可以通过将所有规则集的名称放入数组来使用多个规则集:
保存tslint时,立刻获得lint错误,错误是抱怨Product接口缺少前缀。该规则背后的逻辑是,在读取代码时,如果类型以I开头,我们会立刻知道它是一个接口。
保存tslint.json后,警告错误立即消失。
我们可以从linting过程中排除文件,这对于排除第三方代码很有用,我们可以通过在linterOptions字段的exclude字段中指定文件数组来实现:
前面的配置从linting过程中排除了第三方节点程序包。
为Visual Studio Code中安装另一个扩展名为Prettier的插件,它将自动格式化我们的代码。出来有助于修正代码的样式,还有助于我们遵守某些TSLint规则:
现在已经安装了此扩展,当我们保存TypeScript代码时,将自动为我们很好的格式化它。
本文首先介绍了我们为什么要使用TypeScript构建前端。现在,我们拥有了TypeScript的第一手经验,可以及早发现错误并未我们提供诸如IntellISense之类的生产力功能。我们了解到TypeScript只是JavaScript的扩展。因此,我们可以使用JavaScript中的所有功能以及TypeScript的其他功能。这些附加的功能之一是类型注释,它可以帮助编译器发现错误并点亮功能,例如在代码编辑器中进行代码导航。
我们没有涉及类型的所有内容。但是,现在有足够的知识来构建相当复杂的TypeScript程序。尤其是类,使我们能够很好地队复杂现实世界对象进行建模。我们了解了模块以及它们如何使我们脱离危险的全局。模块使我们能够很好的构建代码并使代码可重用。
我们了解到了有关TypeScript编译器的知识,以及它在不同用例中如何能很好地工作,这是因为它非常易于配置。这在TypeScript与React一起使用时,也非常重要。
TSLint和Prettier是锦上添花。这两个工具的好处是它们可以我们的代码库中保持一致性,从而使代码更具有可读性。