开启TypeScript之旅的简便方式

译文
开发 前端
本文分四个不同的阶段,向您深入浅出地介绍如何仅通过VS Code,去使用TypeScript,而无需打开终端、安装依赖项或初始化NPM项目。

[[437443]]

【51CTO.com快译】不可否认,TypeScript凭着智能感知静态分析(又名“类型检查”)、以及内联文档等功能,已经在J​​avaScript社区中占据了一席之地。这些功能虽然并非TypeScript独有,但是能够在如下方面提高开发团队的生产力,并改进的代码质量:

  • 通过实时的、自动完成的代码建议,实现更快的代码编写。
  • 发现并提示代码中的拼写错误。
  • 方便新的成员熟悉代码库。
  • 方便不同编程能力的团队成员更好地协作。
  • 可以防止破损的代码被自动部署。
  • 方便更加便捷、安全地修改和维护旧的代码。
  • 可用于项目的自动文档化。

下面,我将分不同的阶段,向您深入浅出地介绍如何开启TypeScript之旅。

阶段 1:在JavaScript文件中启用TypeScript

作为一种最为普及的代码编辑器,Visual Studio Code被广泛地用来编写JavaScript。不过,VS Code也内置了TypeScript,能够提供上面提到的智能感知和自动建议等基本功能。例如,我们可以创建一个带有属性hello的对象world。当我们试着去访问该对象的属性时,VS Code会自动推荐hello。不仅如此,它还会告诉我们该属性是一个字符串(string)类型。

这是一个非常基本但挺实用的类型检查。而且,就算代码库中存在少许错误,这样的类型检查也能够识别出来。例如,如果我们不小心将数字传递给了需要字符串类型的函数,那么就会被及时发现。因此,为了启用针对JavaScript文件的全面类型检查,您只需将注释// @ts-check添加到待检查的JavaScript文件的顶部便可。

据此,针对前面的例子,如果我们尝试着用数字类型覆盖对象的hello属性,那么我们将会收到一条“Type ‘number’ is not assignable to type ‘string'”的警告。我们之前的函数之所以不会给出任何错误提示,是因为TypeScript并不知道输入只能是字符串类型。为此,我们可以使用JSDoc向JavaScript添加各种类型。

此处的JSDoc是一个通过使用注释,将上下文文档添加到源代码中的系统。它可以被用于自动生成文档站点。TypeScript支持解析JSDoc的各项注释。对于前面的示例函数,我们可以告诉TypeScript,yell函数的第一个参数是str(字符串)类型,及该函数是一个“字符串”。

现在,当我们向函数传递一个数字时,就会看到一个红色的波浪形警告,而在将鼠标悬停其上方时,会出现“Argument of type ‘number’ is not assignable to parameter of type ‘string’.”的具体警告内容。您可以通过jsdoc.app,学习如何使用JSDoc记录各项内容。

阶段 2:在JavaScript项目中启用TypeScript

如果您处理的是大型JavaScript项目,那么逐一添加// @ts-check到每个文件中,显然过于繁琐。幸运的是,VS Code提供了一些方法,来自动化此类工作。其中的一种方法是将“Check JS”配置设置为true。也就是说,我们在settings.json文件中设置为"javascript.implicitProjectConfig.checkJs": true。

如果您想在项目级别上为团队中彼此协作的每个人都启用此功能,则可以通过将tsconfig.json文件添加到项目的根目录来实现。有关tsconfig.json中各种配置选项的详细信息,请参阅--https://www.staging-typescript.org/tsconfig。

  1. JSON 
  2.   "compilerOptions": { 
  3.     "checkJs"true,               /* Report errors in .js files. */ 
  4.   } 

JSDocs支持许多内置的类型,其中包括:string、number、boolean、array、promise、function等。不过,您可能需要创建某些超出基本定义的类型。例如,在定义一个“Dog”对象类型时,它需要具有“品种(breed)”、“年龄(age)”、以及可选的“名字(name)”属性。那么,我们可以通过JSDoc来进行如下类型的定义:

  1. Plain Text 
  2. /** 
  3.  * @typedef {object} Dog 
  4.  * @property {string} breed 
  5.  * @property {number} age 
  6.  * @property {string} [name
  7.  */ 

除了这种通过语法的方式来定义对象以外,您还可以通过参阅JSDoc文档,获悉更多TypeScript的泛型实用类型

下面,我们来看如何使用types.js文件,来定义各种全局类型,并向代码库中导入类型定义。据此,我们将Dog的类型定义放入该文件中,通过引用相对路径,实现在各种不同文件中导入并使用该类型:

  1. JSON 
  2. /** @type {import('./types).Dog} */ 
  3. const myDog = { 
  4.   breed: 'Chiweenie'
  5.   age: 4, 
  6.   name'Nugget' 

如果需要让Dog能够在同一个文件中的多处使用到该类型,我们则可以在本地重新定义类型,以减少输入:

  1. JSON 
  2. /** @typedef {import('./types).Dog} Dog */ 
  3. /** @type {Dog} */ 
  4. const myDog = { 
  5.   breed: 'Chiweenie'
  6.   age: 4, 
  7.   name'Nugget' 

您可能会发现,就目前而言,由于该文件不属于JavaScript模块,我们无法从types.js文件中导入任何内容。编辑器会提示:“File ‘/path/to/types.js’ is not a module.”。对此,您可以使用CommonJS或ES模块语法,导出该文件。其导出值并不重要,它甚至可以undefined。例如,它可以是下面的任何一行:

  1. Plain Text 
  2. // Works 
  3. module.exports = {} 
  4. // Sure 
  5. exports.merp = '' 
  6. // Why not
  7. export default = null 
  8. // Go for it 
  9. export const thingamabob = undefined 

当然,我们也可以是从第三方库导入的类型定义。其语法虽然非常相似,但是并不会使用相对路径,而是按照名称去引用库。例如,Vue.js(https://vuejs.org/)组件可以被输入为:

  1. Plain Text 
  2. /** @type {import('vue').Component} */ 

当然,并非所有库都会提供类型定义。如果您的库不提供类型定义,那么您可以去absolutetyped.org社区进行检索。VS Code有一个名为“自动类型获取(Automatic Type Acquisition)”的功能,会自动为你查找和安装来自社区的类型定义。

如果您愿意,也可以遵从上述语法,在TypeScript文件中编写类型定义,不过其文件扩展名为.ts。例如,如果想用TypeScript定义上述全局类型,我们可以将文件名更改为“type.ts”,其内容如下:

  1. TypeScript 
  2. export interface Dog { 
  3.   breed: string 
  4.   age: number 
  5.   name?: string 

阶段 3:将TypeScript集成到 CI/CD 管道中

下面,让我们讨论一些更为复杂的问题。如果在代码中引入了错误,我们可以阻止代码的部署吗?在开始讨论之前,我们假设:

  • 您可以自如地使用命令行。
  • 您对NPM已有一定的经验;如果没有,可以通过链接--https://docs.npmjs.com/getting-started,了解NPM的相关基础知识。
  • 您已熟悉CI/CD(持续集成/持续交付)的概念。
  • 您已经拥有一个使用package.json文件初始化了的NPM项目。

我们的目标是在CI/CD环境中运行TypeScript编译器,以便系统判定代码是否存在类型错误。为此,我们需要为CI/CD环境提供一个TypeScript版本,以及一个待运行的脚本。

首先在终端里,我们需要在该项目的同一个文件夹中运行如下命令:

  1. npm install --save-devTypeScript 

它会在本地安装TypeScript,并把Typecript包作为开发依赖项,包含在package.json文件中予以更新。在了解了有哪些依赖项已被安装后,TypeScript可以在不依赖VS Code的情况下服务于该项目。接着,我们可以使用如下命令,更新package.json文件的NPM脚本部分

  1. Plain Text 
  2. "ts""tsc" 

上述命令会添加一个名为ts的新脚本,并运行“tsc”命令(即typescript编译器)。在运行“npm run ts”命令之前,我们需要解决两个问题:

1. TypeScript需要知道待运行文件的路径。

2. TypeScript只适用于.ts文件,而我们只有.js文件。

对此,您需要决定是继续编写JavaScript文件呢,还是去写TypeScript文件?就我而言,我认为将所有内容保留在JavaScript中会更加简单。毕竟TypeScript编译器能够很好地支持JavaScript文件,只不过未能在默认情况下启用罢了。

为了明确地告知TypeScript去检查哪些文件,我们需要使用allowJs配置,来允许它在JavaScript文件上运行。假设我们的JavaScript是写在./src/index.js文件中的,那么我们将有如下选择:

  • 我们可以将“--allowJs ./src/index.js”添加到package.json文件中的NPM脚本中。
  • 我们可以在每次调用NPM脚本:“npm run ts -- --allowJs ./src/index.js”时,添加上述命令。
  • 我们可以在项目的根目录中使用tsconfig.json文件。

由于我们已经拥有一个tsconfig.json文件,因此可以直接使用它。同时,我们需要定义files数组,并将allowJs和noEmit设置为true:

  1. JSON 
  2.   "files": ["./src/index.js"], 
  3.   "compilerOptions": { 
  4.     "checkJs"true,               /* Report errors in .js files. */ 
  5.     "allowJs"true,               /* Allow parsing javascript. */ 
  6.     "noEmit"true,                /* Do not emit outputs. */ 
  7.   } 

由于TypeScript通常被用于转译代码,因此我们可以在此将noEmit配置设置为true。这就意味着,它可以接受各种代码,并以某种方式对其进行转换。例如,它能够接收一个TypeScript文件,然后返回一个JavaScript文件。

运行“npm run ts”命令,我们不会看到任何配置错误,而只是一些与代码相关的错误。例如,在前面的示例中,如果我们试图覆盖被定义为字符串类型的属性,就会产生错误。

至此,我们已经准备好了将这种类型检查,集成到自动化部署的过程中。我们需要确保部署过程能够顺利地调用“npm run ts”命令。

值得一提的是,TypeScript虽然是一个很好的测试套件的补充,但它绝不是自动化测试的替代品。纵然TypeScript可以消除进入代码库时的各种类型错误,但是如果您的项目依赖于自动化部署的话,您还应该做好单元集成测试

TypeScript虽然可能会阻止您在应当运用数字的地方使用字符串,但是不会阻止您在只允许使用正数的情况下使用负数。因此,我建议您在系统中同时实施静态分析和自动化测试。而我最喜欢的JavaScript项目测试工具是Jest

阶段 4:为开源库生成类型定义

definitelytyped.org之类的社区项目可以为TypeScript提供类型定义等支持。我们可以采用当前的设置,而无需其他繁琐的设置,让TypeScript为我们的项目创建类型定义文件。在完成之后,我们可以发布自己的库,以便用户拥有丰富的类型定义,进而协助改善用户与库交互的体验。

首先,我们需要对tsconfig.json文件进行更多的修改。其中包括:删除“noEmit”设置(或将其设置为false),将“declaration”和“emitDeclarationOnly”设置为true,并为“outDir”提供路径。下面展示了新的文件内容:

  1.   "files": ["./src/index.js"], 
  2.   "compilerOptions": { 
  3.     "checkJs"true,               /* Report errors in .js files. */ 
  4.     "allowJs"true,               /* Allow parsing javascript. */ 
  5.     "declaration"true,           /* Generates '.d.ts' file. */ 
  6.     "emitDeclarationOnly"true,   /* Only generate '.d.ts'No JS */ 
  7.     "outDir""./dist",            /* Send output to this directory. */ 
  8.   } 

您可以为“outDir”任选一个路径,以便为生成的类型定义文件提供存放之处。由于我们已经使用了JavaScript,因此无需额外编译步骤,便可将“emitDeclarationOnly”设置为true。在构建步骤中,您也可以使用Babel.jsRollup.js

在生成了类型定义文件,并发送至/dist文件夹后,我们需要修改package.json文件,以便告知NPM各种文件的存在性,并让任何使用库的开发人员受益。为了在NPM处发布内容,我们不但需要注意“name”和“version”属性,还可以通过定义“types”(又名“typings”)属性,来告知TypeScript在哪个文件夹中,查找库的类型定义文件。当然,如果您的类型定义文件(以.d.ts结尾)与代码同处一个文件夹中,则无需上述设置。下面展示了package.json文件的示范性内容:

  1.   "name""nuggetisthebest"
  2.   "version""1.0.0"
  3.   "types""dist"
  4.   "scripts": { 
  5.     "ts""tsc" 
  6.   }, 
  7.   "devDependencies": { 
  8.     "typescript""^4.1.3" 
  9.   } 

请参见NPM文档,以获悉更多有关如何将库发布到NPM处。

禁止在某些代码上运行TypeScript

有时您在CI/CD管道中使用到了TypeScript,但并不希望它报告、甚至阻止项目的部署。对此,我们可以通过如下选项,来予以规避:

  • 在某一行中禁用TypeScript:通过在任意行上添加注释// @ts-ignore,您可以禁用TypeScript对于该行的分析。
  • 在整个文件上禁用TypeScript:如果想禁用TypeScript对整个文件的检查,您可以在文件的顶部添加注释// @ts-nocheck。
  • 在文件组或目录组上禁用TypeScript:tsconfig.json文件有一个配置选项exclude,它允许您定义需要完全忽略的文件和目录。

复杂类型

最终,您可能会需要重载函数(overloaded functions)之类非常复杂的类型定义。您可以在JSDoc中使用各种TypeScript功能,轻松地从TypeScript文件(.ts扩展名)中导入相关的类型。

  1. TypeScript 
  2. /** @type { import('.types.ts').SomeType } */ 
  3. const  someType  = {} 

这意味着在任何复杂的情况下,我们都可以使用常规的TypeScript文件,并将自定义类型导入到JSDoc中,而无需为整个项目编写TypeScript。我们甚至都不需要依赖TypeScript编译器。此外,我们还可以使用.d.ts文件,来声明全局类型,具体请参见--https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html。

小结

总的说来,虽然使用.ts文件比较常见,但是我会基于如下原因,去使用JSDocs方法:

  • 无需额外的构建步骤,只需普通的JavaScript。
  • 可以将代码复制并粘贴到任何JavaScript项目中。
  • 并未增添新的语法,因此容易上手。
  • 将更少的“噪音”引入代码。
  • 由于无需等待编译器,因此开发的速度会更快。

下面是更多有关JSDoc的资源,可供您深入研究:

原文标题:Get Started With TypeScript the Easy Way,作者:Austin Gil

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

责任编辑:华轩 来源: 51CTO
相关推荐

2010-07-16 09:49:34

2021-08-11 15:20:08

自动化

2021-12-09 22:27:30

云计算云计算环境云安全

2011-07-21 09:41:30

SQL ServerDenali

2011-07-21 09:32:33

SQL ServerDenali

2014-07-04 09:43:22

2013-10-10 14:45:13

华为敏捷交换机华为交换机SDN交换机

2021-06-01 08:45:06

智慧城市物联网5G

2022-09-16 13:27:46

能源管理绿色建筑物联网

2022-08-31 18:51:00

DevOps软件开发

2023-04-28 14:38:47

2011-07-21 09:19:38

SQL ServerDenali

2019-08-05 09:44:09

AI人工智能数据

2018-04-16 09:20:45

Windows 10LinuxWSL

2024-04-19 08:28:57

JavaAPI场景

2024-02-28 10:20:08

2015-11-12 17:33:01

去哪儿

2014-04-10 17:46:03

华三巡展华三

2015-01-12 15:40:44

2015-09-09 13:17:53

世界之窗深信服
点赞
收藏

51CTO技术栈公众号