开启TypeScript之旅的简便方式

2724 字丨阅读本文需 6 分钟

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

下面,我将分不同的阶段,向您深入浅出地介绍如何开启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记录各项内容。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

【编辑推荐】

来源:51CTO陈峻

免责声明:凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处本网。非本网作品均来自其他媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如您发现有任何侵权内容,请依照下方联系方式进行沟通,我们将第一时间进行处理。

0赞 好资讯,需要你的鼓励
来自:51CTO
0

参与评论

登录后参与讨论 0/1000

为你推荐

加载中...