跳至主要内容

常见问题解答

我正在使用 ESLint 核心中的规则,但它在 TypeScript 代码中无法正常工作

这是因为 TypeScript 添加了 ESLint 不了解的新功能。

第一步是 查看我们的“扩展”规则列表。扩展规则是扩展基本 ESLint 规则以支持 TypeScript 语法的规则。如果你在这里找到了它,请尝试一下看看它是否适合你。你可以通过禁用基本规则并启用扩展规则来配置它。以下是用 semi 规则的示例

{
"rules": {
"semi": "off",
"@typescript-eslint/semi": "error"
}
}

如果您没有找到现有的扩展规则,或者扩展规则不适用于您的情况,那么您可以查看我们的问题。 贡献指南概述了提出问题的最佳方式

我们每周都会发布新版本的工具。确保您查看最新的“扩展”规则列表提交问题之前。

我收到错误消息,提示“使用默认项目运行多个文件会导致性能问题并减慢代码检查速度”。

这些错误是由使用EXPERIMENTAL_useProjectService allowDefaultProjectForFiles 以及过于宽泛的通配符导致的。allowDefaultProjectForFiles 会为每个包含的“项目外”文件构建一个新的 TypeScript “程序”,这会为每个文件带来性能开销。

要解决此错误,请缩小用于allowDefaultProjectForFiles 的通配符,以包含更少的文件。例如

eslint.config.js
parserOptions: {
EXPERIMENTAL_useProjectService: {
allowDefaultProjectForFiles: [
- "**/*.js",
+ "./*.js"
]
}
}

您可能还需要在您的tsconfig.json 中包含更多文件。例如

tsconfig.json
"include": [
"src",
+ "*.js"
]

如果您无法做到这一点,请在 typescript-eslint 的 typescript-estree 包上提交问题,告诉我们您的用例以及为什么需要更多项目外文件进行代码检查。请务必提供一个最小的可重现示例,以便我们了解您的用例!

我收到错误信息“ESLint 被配置为运行... 但是,该 TSConfig 不包含/这些 TSConfig 中没有一个包含此文件”

这些错误是由 ESLint 配置请求为未包含在 TypeScript 配置中的文件生成类型信息引起的。

修复错误

  • 如果您**不想**对该文件进行 lint
  • 如果您**想**对该文件进行 lint
    • 如果您**不想**使用类型感知 lint对该文件进行 lint

      eslint.config.js
      import tseslint from 'typescript-eslint';

      export default tseslint.config(
      // ... the rest of your config ...
      {
      files: ['**/*.js'],
      extends: [tseslint.configs.disableTypeChecked],
      },
      );
      • 或者,要手动为文件禁用类型检查,您可以将 parserOptions: { project: false } 设置为要排除的文件的覆盖。
    • 如果您**想**使用类型感知 lint对该文件进行 lint

      • 检查您提供给 parserOptions.project 的每个 TSConfig 的 include 选项 - 您必须确保所有文件都与 include glob 匹配,否则我们的工具将无法找到它。
        • 如果文件是 .cjs.js.mjs 文件,请确保已启用 allowJs
      • 如果您的文件不应属于您现有的 tsconfig 之一(例如,它是在仓库中本地运行的脚本/工具),那么请考虑在您的项目根目录中创建一个新的 tsconfig(我们建议将其命名为 tsconfig.eslint.json),并在其 include 中列出此文件。有关示例,您可以查看我们之前在此仓库中使用的配置。

更多详情

此错误可能是由两件事的组合引起的。

  • 源文件的 ESLint 配置在 parserOptions.project 中指定了至少一个 TSConfig 文件。
  • 这些 TSConfig 文件中没有一个包含要进行代码风格检查的源文件。

当为解析源文件指定 TSConfig 文件时,@typescript-eslint/parser 将使用第一个能够包含该源文件的 TSConfig(根据 aka.ms/tsconfig#include)来生成类型信息。但是,如果指定的 TSConfig 中没有包含源文件,解析器将无法生成类型信息。

此错误最常发生在未包含在项目 TSConfig 中的配置文件或类似文件上。例如,许多项目都有以下文件:

  • 一个 .eslintrc.cjs / eslint.config.js,其中 parserOptions.project: ["./tsconfig.json"]
  • 一个 tsconfig.json,其中 include: ["src"]

在这种情况下,在具有 ESLint 扩展的 IDE 中查看文件将显示错误通知,表明该文件无法进行代码风格检查,因为它未包含在 tsconfig.json 中。

有关更多信息,请参阅我们关于 类型感知代码风格检查 的文档。

我收到错误提示“该文件必须包含在至少一个提供的项目中”。

您正在使用过时的 @typescript-eslint/parser 版本。更新到最新版本以查看此错误消息的更详细版本,解释 以上

如何启用 @typescript-eslint 规则?

首先确保您已阅读文档并了解 ESLint 配置文件。

我们的 规则文档 在“选项”标题下详细介绍了每个规则支持的选项。我们使用 TypeScript 类型来描述规则的 Options 元组类型,您可以使用它来配置规则。在您的配置文件中,rules 对象的键是您要配置的规则的名称,值遵循以下形式

type Severity = 'off' | 'warn' | 'error';
type RuleConfig =
| Severity
| [Severity]
| [
Severity,
// Options is the tuple type from the rule docs
...Options,
];

一些示例

eslint.config.js
export default tseslint.config(
// ... the rest of your config ...
{
rules: {
// turns a rule on with no configuration (i.e. uses the default configuration)
'@typescript-eslint/array-type': 'error',
// turns on a rule with configuration
'@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }],
},
},
);

typescript-eslint 认为我的变量永远不会为 nullish / 是 any / 等等,但对我来说显然不是这样。

我们的类型感知规则几乎总是信任 TypeScript 编译器提供的类型信息。因此,检查我们的规则是否正常运行的简单方法是检查所讨论变量的类型,例如通过在 IDE 中悬停在它上面。

如果 IDE 也显示类型永远不会为 nullish / 是 any,则需要修复类型。一个非常常见的情况是 no-unnecessary-condition 规则。以这段代码为例

let condition = false;

const f = () => (condition = true);
f();

if (condition) {
//^^^^^^^^^ Unnecessary conditional, value is always falsy.
}

你可以在 IDE 中将鼠标悬停在 condition 上,可以看到它的类型实际上是字面量类型 false。在这种情况下,typescript-eslint 无法比 TypeScript 本身更了解,因此你需要通过修复类型来修复报告,例如通过断言 (let condition = false as boolean)。

如果 IDE 提供的类型信息与 typescript-eslint 报告中的类型信息不同,请确保用于 IDE、typescript-eslint 和 tsc 的 TypeScript 设置相同:相同的 TypeScript 版本、相同的类型检查编译器选项以及项目中包含的相同文件。例如,如果类型在另一个文件中声明,但该文件未包含在内,则该类型将变为 any,并导致我们的 no-unsafe-* 规则报告错误。

我可以在 typescript-eslint 中使用 ESLint 的 --cache 吗?

ESLint 的 --cache 选项 基于每个文件进行缓存。你可以使用它,但它只对无类型规则可靠地工作 - 即使这样,也不总是可靠的。

任何检查跨文件逻辑的 ESLint 规则,包括来自 eslint-plugin-import 的许多规则,都会创建跨文件依赖关系。类型化 lint 规则 在实践中几乎总是依赖于跨文件的类型。ESLint 的缓存没有考虑这些跨文件依赖关系。

我们不建议使用 --cache

我使用了一个需要自定义文件扩展名的框架(如 Vue),并且我遇到了错误,例如“您应该在您的配置中添加 parserOptions.extraFileExtensions

你可以使用 parserOptions.extraFileExtensions 来指定一个允许的非 TypeScript 扩展数组,例如

eslint.config.js
export default tseslint.config(
// ... the rest of your config ...
{
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
project: ['./tsconfig.json'],
extraFileExtensions: ['.vue'],
},
},
},
);

我在解析 .vue 文件中的 TypeScript 时遇到了错误

如果你在解析 .vue 文件时遇到问题,可能是因为解析器(如 vue-eslint-parser)需要解析 .vue 文件。在这种情况下,你可以将 @typescript-eslint/parser 移动到 parserOptions 中,并将 vue-eslint-parser 用作顶级解析器。

eslint.config.js
import tseslint from 'typescript-eslint';
import vueParser from 'vue-eslint-parser';

export default tseslint.config(
// ... the rest of your config ...
{
languageOptions: {
parser: tseslint.parser,
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
sourceType: 'module',
},
},
},
);

parserOptions.parser 选项也可以指定一个对象来指定多个解析器。有关更多详细信息,请参阅 vue-eslint-parser 使用指南

我的一个 lint 规则在纯 JavaScript 文件上无法正常工作

这是预料之中的 - ESLint 规则故意不检查文件扩展名,因为它会导致在使用非标准扩展名的环境中出现问题(例如,.vue.md 文件都可以包含要进行 lint 的 TypeScript 代码)。

如果您有一些纯 JavaScript 代码,您不想对其应用某些 lint 规则,那么您可以使用 ESLint 的 overrides 配置 来关闭某些规则,甚至根据 glob 模式更改解析器。

我应该在转译后的输出 JavaScript 文件上运行 ESLint 吗?

不。

源 TypeScript 文件包含所有输出 JavaScript 文件的内容,以及类型注释。对输出 JavaScript 文件进行 lint 没有任何好处。

TypeScript 应该在本地安装

确保您已在本地安装 TypeScript,例如通过使用 npm install typescript(而不是 npm install -g typescript),或使用 yarn add typescript(而不是 yarn global add typescript)。有关更多信息,请参见 #2041

如何禁止 <特定语言特性>

ESLint 核心包含规则 no-restricted-syntax。此通用规则允许您为要禁止的代码指定 选择器,以及自定义错误消息。

您可以使用 AST 可视化工具,例如 typescript-eslint playground > 选项 > AST 资源管理器,在左侧边栏中选择 ESTree,以帮助确定要禁止的 AST 结构。

例如,您可以使用以下配置之一禁止枚举(或某些变体)

{
"rules": {
"no-restricted-syntax": [
"error",
// ban all enums
{
"selector": "TSEnumDeclaration",
"message": "My reason for not using any enums at all",
},

// ban just const enums
{
"selector": "TSEnumDeclaration[const=true]",
"message": "My reason for not using const enums",
},

// ban just non-const enums
{
"selector": "TSEnumDeclaration:not([const=true])",
"message": "My reason for not using non-const enums",
},
],
},
}

为什么我在 ESLint 输出中看不到 TypeScript 错误?

TypeScript 的编译器(或您的构建链可能是任何东西)专门设计和构建用于验证代码库的正确性。我们的工具不会重现 TypeScript 提供的错误,因为这样做会减慢 lint 运行速度 [1],并重复 TypeScript 已经为您输出的错误。

相反,我们的工具存在于 增强 TypeScript 的内置检查,使用 lint 规则以超越仅验证代码的运行时正确性的新方式使用类型信息。

[1] - TypeScript 延迟计算类型信息,因此我们要求它从编译器生成错误将需要每个文件额外花费约 100 毫秒。这听起来并不多,但根据代码库的大小,它很容易累积到 lint 运行的几秒钟到几分钟之间。

我从 no-undef 规则中得到关于全局变量未定义的错误,即使没有 TypeScript 错误

no-undef lint 规则不使用 TypeScript 来确定存在的全局变量 - 相反,它依赖于 ESLint 的配置。

我们强烈建议您不要在 TypeScript 项目中使用 no-undef lint 规则。它提供的检查已经由 TypeScript 提供,无需配置 - TypeScript 只是做得更好。

从我们的 v4.0.0 版本开始,这也适用于类型。如果您使用来自第三方包的全局类型(即来自 @types 包的任何内容),那么您必须适当地配置 ESLint 来定义这些全局类型。例如;来自 @types/reactJSX 命名空间是一个全局第三方类型,您必须在您的 ESLint 配置中定义它。

请注意,对于包含 JavaScript 和 TypeScript 的混合项目,no-undef 规则(像任何规则一样)可以单独关闭 TypeScript 文件,如下所示

eslint.config.js
import tseslint from 'typescript-eslint';

export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.{ts,tsx,mts,cts}'],
rules: {
'no-undef': 'off',
},
},
);

如果您选择保留 ESLint no-undef lint 规则,您可以 在您的 ESLint 配置中手动定义允许的 globals,或者您可以使用其中一个 预定义的环境 (env) 配置

如何检查已安装的版本?

如果您有多个版本的工具,可能会导致各种错误。这是因为 ESLint 可能会根据您的运行方式在每次运行时加载不同的版本 - 从而导致 lint 结果不一致。

在项目根目录安装我们的工具并不意味着只安装了一个版本。您的一个或多个依赖项可能也依赖于我们的工具,这意味着 `npm` / `yarn` 将额外安装该版本供该包使用。例如,`react-scripts`(`create-react-app` 的一部分)依赖于我们的工具。

您可以使用以下命令检查项目中安装了哪些版本

npm list @typescript-eslint/eslint-plugin @typescript-eslint/parser

如果您看到安装了多个版本,则必须使用 yarn resolutions 强制使用单个版本,或者您必须将根版本降级以匹配依赖项版本。

在这种情况下,最好的做法是等待您的依赖项发布支持我们最新版本的版本。

如何指定 TypeScript 版本 / `parserOptions.typescriptLocation`?

您不能,也不应该。

您应该使用与项目其余部分相同的 TypeScript 版本进行代码风格检查。TypeScript 版本在边缘情况下通常会有细微的差异,这会导致 typescript-eslint 规则和编辑器信息之间出现矛盾的信息。例如

  • @typescript-eslint/strict-boolean-expressions 可能使用 TypeScript 版本 *X*,并认为变量是 `string[] | undefined`
  • TypeScript 本身可能处于版本 *X+1-beta*,并认为变量是 `string[]`

有关更多详细信息,请参阅 此问题评论

更改一个文件时,IDE 中其他文件的代码风格检查没有反映出来

简而言之:重新启动 ESLint 服务器以强制更新。

ESLint 目前没有办法告诉我们这样的解析器何时在磁盘上更改了任意文件。这意味着,如果您更改了文件 A,而文件 A 被文件 B 导入,它不会更新文件 B 的代码风格检查缓存,即使文件 B 的文本内容已更改。有时,唯一的解决方案是完全重新启动 ESLint 编辑器扩展。

有关更多信息,请参阅 此问题评论

提示

VS Code 的 ESLint 扩展 提供了一个 ESLint: Restart ESLint Server 操作。

对于跨文件更改,我收到 no-unsafe-* 的警告

请参阅 更改一个文件后,我的 IDE 在 lint 其他文件时没有反映这些更改。像 no-unsafe-argumentno-unsafe-assignmentno-unsafe-call 这样的规则经常受到影响。

“'<key>' 属性在 '<type>' 节点上已弃用。请使用 '<key>' 代替。” 警告

如果您看到此警告,则可能是您正在使用尚未更新以支持 typescript-eslint v6 的 ESLint 插件(或其他工具)。请确保您使用的是每个 ESLint 插件(和其他工具)的最新版本。

如果您使用了许多 ESLint 插件,并且已将每个插件更新到最新版本,但您不确定哪个插件导致了此警告,请尝试以下任一或两种方法:

  • 使用 --trace-deprecation 运行(例如 npx cross-env NODE_OPTIONS=--trace-deprecation npm run lint
  • 一次禁用一半的插件,以缩小范围,确定是哪个插件导致了问题。

然后,请确保每个插件的 GitHub 问题都要求发布支持 typescript-eslint v6 的版本。

提示

对于在仍然需要支持 typescript-eslint v5 的插件中更新 ESLint 规则的开发人员:您可能需要使用 || 回退到旧的属性键,如果新的属性键不存在。

- node.typeParameters
+ node.typeArguments || node.typeParameters

有关更多上下文,请参阅 某些属性命名为 typeParameters 而不是 typeArguments 问题,以及实现 fix: 将 typeParameters 重命名为 typeArguments(必要时) 的拉取请求。

typescript-eslint v6 发布文章 中提供了有关 typescript-eslint v6 的更多信息。

我的 lint 速度非常慢

如果您认为遇到性能问题,请查看我们的 性能故障排除文档

TypeScript 项目引用是否受支持?

是的,但仅适用于 EXPERIMENTAL_useProjectService

有关更多详细信息,请参阅 问题 #2094,讨论项目引用