TypeScript——JavaScript类型检查
JavaScript类型检查1、编译JavaScript2、JavaScript类型检查2.1、--checkJs2.2、// ts-nocheck2.3、// ts-check2.4、// ts-ignore3、JSDoc与类型3.1、 typedef3.2、type3.3、param3.4、return和returns3.5、extends和修饰符由于TypeScript语言是JavaScript语言的超集因此JavaScript程序是合法的TypeScript程序。TypeScript编译器能够像处理TypeScript程序一样去处理JavaScript程序例如对JavaScript程序执行类型检查和编译JavaScript程序。本节将介绍如何配置TypeScript编译器使其能够对JavaScript程序执行类型检查以及编译JavaScript程序。此外我们还会介绍TypeScript编译器是如何从JavaScript文档工具JSDoc中提供类型信息的。1、编译JavaScript在一个工程中可能既存在TypeScript代码也存在JavaScript代码。例如一个Type-Script工程依赖于某个JavaScript代码库又或者一个工程正在从JavaScript向TypeScript进行迁移。如果TypeScript工程中的JavaScript程序也是工程的一部分那么就需要使用“–allowJs”编译选项来配置TypeScript编译器。在默认情况下编译器只会将“.ts”和“.tsx”文件添加到编译文件列表而不会将“.js”和“.jsx”文件添加到编译文件列表。如果想要让编译器去编译JavaScript文件那么就需要启用“–allowJs”编译选项。在启用了“–allowJs”编译选项后工程中的“.js”和“.jsx”文件也会被添加到编译文件列表。假设当前工程目录结构如下C:\app -- src -- index.js在“C:\app”目录下运行tsc命令来编译“index.js”文件示例如下tsc src/index.js运行上述命令时会出现如下错误因为在默认情况下编译器不支持编译JavaScript文件error TS6054: 不支持src/foo.js文件的扩展名。 支持的扩展名为.ts, .tsx, .d.ts。在“C:\app”目录下运行tsc命令来编译“index.js”文件并启用“–allowJs”编译选项。示例如下tsc src/index.js--allowJs--outDirdist在启用了“–allowJs”编译选项后编译器能够像编译TypeScript文件一样去编译JavaScript文件。此例中我们还必须指定一个除“C:\app\src”之外的目录作为输出文件目录否则编译器将报错。因为如果在“C:\app\src”目录下生成编译后的“index.js”文件那么它将会覆盖源“index.js”文件这是不允许的。2、JavaScript类型检查在默认情况下TypeScript编译器不会对JavaScript文件进行类型检查。就算启用了“–allowJs”编译选项编译器依然不会对JavaScript代码进行类型检查。2.1、–checkJsTypeScript 2.3提供了一个“–checkJs”编译选项。当启用了该编译选项时编译器能够对“.js”和“.jsx”文件进行类型检查。“–checkJs”编译选项必须与“–allowJs”编译选项一起使用。假设当前工程目录结构如下C:\app -- src -- index.js“index.js”文件的内容如下01 const elementdocument.getElementById(123);02 // ~~~ 03 // 参数类型错误应该为 string 类型在此例的JavaScript代码中存在一个类型错误那就是“getElementById”方法的参数类型应该为字符串类型而实际参数的类型为数字类型。在“C:\app”目录下运行tsc命令来编译“index.js”文件。若不启用“–checkJs”编译选项则不会产生编译错误示例如下tsc src/index.js--allowJs--outDirdist在“C:\app”目录下运行tsc命令来编译“index.js”文件。若启用了“–checkJs”编译选项和“–allowJs”编译选项则会产生编译错误示例如下tsc src/index.js--allowJs--checkJs--outDirdist编译器能够检查出“getElementById”方法的参数类型错误如下所示src/index.js:1:41 - error TS2345: Argument oftype123is not assignable to parameter oftypestring.2.2、// ts-nocheck“// ts-nocheck”是一个注释指令如果为JavaScript文件添加该注释那么相当于告诉编译器不对该JavaScript文件进行类型检查。此外该指令也可以在TypeScript文件中使用。假设当前工程目录结构如下C:\app -- src -- index.js“index.js”文件的内容如下// ts-nocheckconstelementdocument.getElementById(123);// ~~~// 参数类型错误应该为 string 类型在“C:\app”目录下运行tsc命令来编译“index.js”文件并启用“–checkJs”编译选项和“–allowJs”编译选项。示例如下tsc src/index.js--allowJs--checkJs--outDirdist此例中虽然“index.js”存在类型错误但是编译器不会报错。因为我们使用“// ts-nocheck”注释指令禁用了对“index.js”文件的类型检查。2.3、// ts-check如果一个JavaScript文件中添加了“// ts-check”注释指令那么编译器将对该Java-Script文件进行类型检查不论是否启用了“–checkJs”编译选项。假设当前工程目录结构如下C:\app -- src -- index.js“index.js”文件的内容如下// ts-checkconstelementdocument.getElementById(123);// ~~~// 参数类型错误应该为 string 类型在“C:\app”目录下运行tsc命令来编译“index.js”文件但不启用“–checkJs”编译选项。示例如下tsc src/index.js--allowJs--outDirdist此例中虽然没有启用“–checkJs”编译选项但是编译器仍然会对“index.js”文件进行类型检查并显示如下的错误提示src/index.js:3:41 - error TS2345: Argument oftype123is not assignable to parameter oftypestring.2.4、// ts-ignore“// ts-ignore”注释指令的作用是忽略对某一行代码进行类型检查。当在代码中使用“// ts-ignore”注释指令时编译器不会对与该指令相邻的后面一行代码进行类型检查。此外该指令也可以在TypeScript文件中使用。假设当前工程目录结构如下C:\app -- src -- index.js“index.js”文件的内容如下// ts-ignoreconstelement1document.getElementById(123);// ~~~// 参数类型错误应该为 string 类型constelement2document.getElementById(456);// ~~~// 参数类型错误应该为 string 类型在“C:\app”目录下运行tsc命令来编译“index.js”文件并启用“–checkJs”编译选项和“–allowJs”编译选项示例如下tsc src/index.js--allowJs--checkJs--outDirdist运行tsc命令的输出结果如下src/index.js:6:42 - error TS2345: Argument oftype456is not assignable to parameter oftypestring.此例中编译器会对“index.js”文件进行类型检查。因为我们在第1行添加了“// ts-ignore”注释指令所以编译器不会对第2行进行类型检查。但第6行代码不受影响编译器将对其进行类型检查。最后的输出结果也显示了编译器只检查出第6行中的类型错误。3、JSDoc与类型JSDoc[插图]是一款知名的为JavaScript代码添加文档注释的工具。JSDoc利用了JavaScript语言中的多行注释语法并结合使用特殊的“JSDoc标签”来为代码添加丰富的描述信息。在使用JSDoc时有以下两个基本要求代码注释必须以“/”开始其中星号的数量必须为两个。若使用了“/”“/*”或其他形式的多行注释则JSDoc会忽略该条注释。代码注释与它描述的代码处于相邻的位置并且注释在上代码在下。下例中使用JSDoc描述了“sayHello”函数能够接受一个string类型的参数。其中“param”是一个JSDoc标签如下所示/** * param {string} somebody */functionsayHello(somebody){alert(Hello somebody);}TypeScript编译器既能够自动推断出大部分JavaScript代码的类型信息也能够从JSDoc中提取类型信息。接下来我们将介绍TypeScript编译器支持的部分JSDoc标签。3.1、 typedef“typedef”标签能够创建自定义类型。通过“typedef”标签创建的自定义类型等同于TypeScript中的类型别名。示例如下/** * typedef {(number | string)} NumberLike */此例中创建了一个名为NumberLike的类型它是由number类型和string类型构成的联合类型。该类型等同于如下类型别名定义typeNumberLikestring|number;3.2、type“type”标签能够定义变量的类型。示例如下/** * type {string} */leta;此例中定义了变量a的类型为string。在“type”标签中可以使用由“typedef”标签创建的类型。示例如下/** * typedef {(number | string)} NumberLike *//** * type {NumberLike} */leta0;在“type”标签中允许使用TypeScript中的类型及其语法。示例如下/**type {true | false} */leta;/** type {number[]} */letb;/** type {Arraynumber} */letc;/** type {{ readonly x: number, y?: string }} */letd;/** type {(s: string, b: boolean) number} */lete;3.3、param“param”标签用于定义函数参数类型。示例如下/** * param {string} x - A string param. */functionfoo(x){}若函数参数是可选参数则需要将参数名置于一对中括号“[]”中。示例如下/** * param {string} [x] - An optional param. */functionfoo(x){}在定义可选参数时还可以为它指定一个默认值。示例如下/** * param {string} [xbar] - An optional param */functionfoo(x){}此例中声明了参数x的默认值为字符串bar。3.4、return和returns“return”和“returns”标签的作用相同两者都用于定义函数返回值类型。它的用法如下所示/** * return {boolean} */functionfoo(){returntrue;}/** * returns {number} */functionbar(){return0;}3.5、extends和修饰符“extends”标签用于定义继承的基类。“public”“protected”“private”标签分别用于定义类的公有成员、受保护成员和私有成员。“readonly”标签用于定义只读成员。示例如下classBase{/** * public * readonly */x0;/** * protected */y0;}/** * extends {Base} */classDerivedextendsBase{/** * private */z0;}