前言
ESLint 是一个非常流行的 JavaScript 代码检查工具,跟 TypeScript 一起使用可以大大提高代码质量和可维护性。本文将介绍 ESLint 和 TypeScript 结合使用时一些需要注意的事项,并提供一些示例代码来帮助你更好地理解。
安装和基础配置
在开始使用 ESLint 和 TypeScript 之前,你需要先安装它们。
安装 ESLint 和 TypeScript:
npm install eslint typescript --save-dev
接下来,你需要创建一个 ESLint 配置文件。可以使用 ESLint 自带的初始化命令,通过命令行交互来创建配置文件:
npx eslint --init
在初始化中,你需要选择配置文件的类型、使用分号还是不使用分号、要不要使用 ECMAScript 模块等等。
在选择模块选项时,你需要选择使用 TypeScript。
最终生成的 ESLint 配置文件大致如下:
-- -------------------- ---- ------- - ------ - ---------- ----- ------ ---- -- ---------- - --------------------- ----------------------------------------------- --------------------------------------- -- --------- ---------------------------- ---------------- - -------------- ----- ------------- -------- -- ---------- - -------------------- -- -------- - ------- --------- ---------- --------- --------- --------- - -
其中,extends
中的三个配置项分别代表:
eslint:recommended
:ESLint 官方推荐的规则;plugin:@typescript-eslint/eslint-recommended
:TypeScript ESLint 插件推荐的规则;plugin:@typescript-eslint/recommended
:TypeScript ESLint 插件推荐的规则,已经包含了plugin:@typescript-eslint/eslint-recommended
的规则。
parser
配置使用了 @typescript-eslint/parser
,这是针对 TypeScript 的 ESLint 解析器。
最后,使用 TypeScript 来解析代码的时候,需要在 ESLint 配置文件的 parserOptions
部分添加一个 tsconfig.json
的配置文件路径,比如:
{ "parserOptions": { "project": "./tsconfig.json", "ecmaVersion": 2020, "sourceType": "module" } }
类型检查规则配置
由于 TypeScript 增加了类型检查,ESLint 中的一些规则需要调整以适应 TypeScript 的类型系统。
由于 ESLint 的规则是基于 AST 而非源代码的文本,所以我们需要使用 TypeScript ESLint 插件来转换 AST,从而在规则检查时考虑 TypeScript 的类型。
下面是一些常见的类型检查规则配置:
no-unused-vars
默认情况下,ESLint 的 no-unused-vars
规则只检测未使用的变量和参数,而不检测未使用的类型。这可能会导致一些类型声明被警告。
在使用 TypeScript 时,可以将 no-unused-vars
规则关闭,使用 TypeScript ESLint 插件内置的 @typescript-eslint/no-unused-vars
规则来代替:
{ "rules": { "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] } }
argsIgnorePattern
表示哪些命名参数不需要检测,可以使用正则表达式来指定。
另外,由于 TypeScript 的类型检查是在编辑时进行的,不同于运行时的 JavaScript,所以在遇到未使用的类型的情况下,可以使用 _ as
操作符来抑制警告。比如:
-- -------------------- ---- ------- --------- ------ - ----- ------- ---- ------- - ----- -- ------ - - ----- ------ ---- --- - -- -------
no-undef
使用 ESLint 的默认配置时,ESLint 会检查你使用的所有变量是否都已经定义过。但是,由于 TypeScript 的类型检查已经执行了这个任务,所以在使用 TypeScript 时,我们需要禁用 no-undef
规则并且使用 TypeScript 的类型检查代替它。
{ "rules": { "no-undef": "off", "@typescript-eslint/no-undef": "error" } }
no-unexpected-multiline
由于 TypeScript 在某些情况下可以自动插入分号,因此代码行末尾不应该出现未插入分号的代码(对于不同的语言级别,TypeScript 行为是不同的)。因此,no-unexpected-multiline
规则需要与 TypeScript 集成。
{ "rules": { "no-unexpected-multiline": "off", "@typescript-eslint/no-unexpected-multiline": "error" } }
其他规则
可以参考 TypeScript ESLint 插件提供的 recommended
规则集,其中封装了一些与 TypeScript 集成的规则。
{ "extends": [ "plugin:@typescript-eslint/recommended" ] }
避免类型声明冗余
在 TypeScript 中,类型声明会重复。比如以下代码:
const value: string = "foo";
这里使用了两次类型声明:string
。在一些情况下,可能会出现冗余的类型声明,如下:
-- -------------------- ---- ------- --------- ------ - ----- ------- ---- ------- - ----- ------- ------ - - ----- ------ ---- --- --
这里有一次类型声明是冗余的。为了避免冗余的类型声明,可以使用 ESLint 插件 eslint-plugin-import
,这个插件会检查导入的模块,尝试自动推断类型。
安装 eslint-plugin-import
:
npm install eslint-plugin-import --save-dev
在 ESLint 配置文件中添加:
-- -------------------- ---- ------- - ---------- - -------- -- -------- - --------------- ------ ------------------- ------ ----------------- ------ ---------------- ------ ----------------------- ------ ------------------------------------ ------ -------------------------- ------ ------------------------------------ ----- - -
其中,以上规则是针对路径和依赖检查的规则,都与类型推断无关,这里设置为 off
。
现在,你可以尝试写出以下代码:
-- -------------------- ---- ------- ------ - ---------- ------ - ---- ---------------- ------------ --------- ----------- ------------ ----------------------- ---------- ------------------------- -- ------ ----- ------------ - ----- - --- ----- -------------------------- ------- ---- ---- -- -
在 api
变量上,你不需要使用类型声明,ESLint 插件 eslint-plugin-import
已经自动推断出了类型。
结论
TypeScript 与 ESLint 结合使用可以帮助我们减少代码错误和易维护性,不过需要注意一些细节,如类型检查规则和类型声明冗余。结合本文中提供的示例代码和配置,可以更好地使用 TypeScript 和 ESLint 开发前端代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/66f7bed6c5c563ced5a8bccf