常见问题解答
我正在使用 ESLint 核心中的规则,但它在 TypeScript 代码中无法正常工作
这是因为 TypeScript 添加了 ESLint 不了解的新功能。
第一步是 查看我们的“扩展”规则列表。扩展规则是扩展基本 ESLint 规则以支持 TypeScript 语法的规则。如果你在这里找到了它,请尝试一下看看它是否适合你。你可以通过禁用基本规则并启用扩展规则来配置它。以下是用 semi
规则的示例
{
"rules": {
"semi": "off",
"@typescript-eslint/semi": "error"
}
}
如果您没有找到现有的扩展规则,或者扩展规则不适用于您的情况,那么您可以查看我们的问题。 贡献指南概述了提出问题的最佳方式。
我们每周都会发布新版本的工具。请确保您查看最新的“扩展”规则列表在提交问题之前。
我收到错误消息,提示“使用默认项目运行多个文件会导致性能问题并减慢代码检查速度”。
这些错误是由使用EXPERIMENTAL_useProjectService
allowDefaultProjectForFiles
以及过于宽泛的通配符导致的。allowDefaultProjectForFiles
会为每个包含的“项目外”文件构建一个新的 TypeScript “程序”,这会为每个文件带来性能开销。
要解决此错误,请缩小用于allowDefaultProjectForFiles
的通配符,以包含更少的文件。例如
parserOptions: {
EXPERIMENTAL_useProjectService: {
allowDefaultProjectForFiles: [
- "**/*.js",
+ "./*.js"
]
}
}
您可能还需要在您的tsconfig.json
中包含更多文件。例如
"include": [
"src",
+ "*.js"
]
如果您无法做到这一点,请在 typescript-eslint 的 typescript-estree 包上提交问题,告诉我们您的用例以及为什么需要更多项目外文件进行代码检查。请务必提供一个最小的可重现示例,以便我们了解您的用例!
我收到错误信息“ESLint 被配置为运行... 但是,该 TSConfig 不包含/这些 TSConfig 中没有一个包含此文件”
这些错误是由 ESLint 配置请求为未包含在 TypeScript 配置中的文件生成类型信息引起的。
修复错误
- 如果您**不想**对该文件进行 lint
- 使用ESLint 提供的选项之一来忽略文件,即
.eslintignore
文件或ignorePatterns
配置。
- 使用ESLint 提供的选项之一来忽略文件,即
- 如果您**想**对该文件进行 lint
-
如果您**不想**使用类型感知 lint对该文件进行 lint
- 使用ESLint 的
overrides
配置以及我们的disable-type-checked
配置,为该类型的文件禁用类型检查。
- 扁平配置
- 传统配置
eslint.config.jsimport tseslint from 'typescript-eslint';
export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.js'],
extends: [tseslint.configs.disableTypeChecked],
},
);.eslintrc.cjsmodule.exports = {
// ... the rest of your config ...
overrides: [
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['./**/*.js'],
},
],
};- 或者,要手动为文件禁用类型检查,您可以将
parserOptions: { project: false }
设置为要排除的文件的覆盖。
- 使用ESLint 的
-
如果您**想**使用类型感知 lint对该文件进行 lint
- 检查您提供给
parserOptions.project
的每个 TSConfig 的include
选项 - 您必须确保所有文件都与include
glob 匹配,否则我们的工具将无法找到它。- 如果文件是
.cjs
、.js
或.mjs
文件,请确保已启用allowJs
。
- 如果文件是
- 如果您的文件不应属于您现有的 tsconfig 之一(例如,它是在仓库中本地运行的脚本/工具),那么请考虑在您的项目根目录中创建一个新的 tsconfig(我们建议将其命名为
tsconfig.eslint.json
),并在其include
中列出此文件。有关示例,您可以查看我们之前在此仓库中使用的配置。
- 检查您提供给
-
更多详情
此错误可能是由两件事的组合引起的。
- 源文件的 ESLint 配置在
parserOptions.project
中指定了至少一个 TSConfig 文件。 - 这些 TSConfig 文件中没有一个包含要进行代码风格检查的源文件。
- 请注意,具有相同名称但扩展名不同的文件可能无法被 TypeScript 识别:请参阅
parserOptions.project
文档。
- 请注意,具有相同名称但扩展名不同的文件可能无法被 TypeScript 识别:请参阅
当为解析源文件指定 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 配置文件。
- 阅读我们的入门指南,以确保您的配置正确设置以开始配置我们的规则。
- 查看 ESLint 关于配置规则的文档,以确保您了解如何配置规则。
我们的 规则文档 在“选项”标题下详细介绍了每个规则支持的选项。我们使用 TypeScript 类型来描述规则的 Options
元组类型,您可以使用它来配置规则。在您的配置文件中,rules
对象的键是您要配置的规则的名称,值遵循以下形式
type Severity = 'off' | 'warn' | 'error';
type RuleConfig =
| Severity
| [Severity]
| [
Severity,
// Options is the tuple type from the rule docs
...Options,
];
一些示例
- 扁平配置
- 传统配置
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 }],
},
},
);
module.exports = {
// ... 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 扩展数组,例如
- 扁平配置
- 传统配置
export default tseslint.config(
// ... the rest of your config ...
{
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
project: ['./tsconfig.json'],
extraFileExtensions: ['.vue'],
},
},
},
);
module.exports = {
// ... the rest of your config ...
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
extraFileExtensions: ['.vue'],
},
};
我在解析 .vue 文件中的 TypeScript 时遇到了错误
如果你在解析 .vue 文件时遇到问题,可能是因为解析器(如 vue-eslint-parser
)需要解析 .vue
文件。在这种情况下,你可以将 @typescript-eslint/parser
移动到 parserOptions
中,并将 vue-eslint-parser
用作顶级解析器。
- 扁平配置
- 传统配置
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',
},
},
},
);
module.exports = {
// ... the rest of your config ...
parser: '@typescript-eslint/parser',
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.vue'],
},
};
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/react
的 JSX
命名空间是一个全局第三方类型,您必须在您的 ESLint 配置中定义它。
请注意,对于包含 JavaScript 和 TypeScript 的混合项目,no-undef
规则(像任何规则一样)可以单独关闭 TypeScript 文件,如下所示
- 扁平配置
- 传统配置
import tseslint from 'typescript-eslint';
export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.{ts,tsx,mts,cts}'],
rules: {
'no-undef': 'off',
},
},
);
module.exports = {
// ... the rest of your config ...
overrides: [
{
files: ['*.ts', '*.mts', '*.cts', '*.tsx'],
rules: {
'no-undef': 'off',
},
},
],
};
如果您选择保留 ESLint no-undef
lint 规则,您可以 在您的 ESLint 配置中手动定义允许的 globals
集,或者您可以使用其中一个 预定义的环境 (env
) 配置。
如何检查已安装的版本?
如果您有多个版本的工具,可能会导致各种错误。这是因为 ESLint 可能会根据您的运行方式在每次运行时加载不同的版本 - 从而导致 lint 结果不一致。
在项目根目录安装我们的工具并不意味着只安装了一个版本。您的一个或多个依赖项可能也依赖于我们的工具,这意味着 `npm` / `yarn` 将额外安装该版本供该包使用。例如,`react-scripts`(`create-react-app` 的一部分)依赖于我们的工具。
您可以使用以下命令检查项目中安装了哪些版本
- npm
- Yarn
- pnpm
npm list @typescript-eslint/eslint-plugin @typescript-eslint/parser
yarn list --pattern "@typescript-eslint/eslint-plugin|@typescript-eslint/parser"
pnpm 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-argument
、no-unsafe-assignment
和 no-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,讨论项目引用。