DevToolBox免费
博客

ESLint 9 完全指南:Flat Config、TypeScript 和现代 Linting (2026)

19 分钟阅读作者 DevToolBox Team

ESLint 是 JavaScript 和 TypeScript 领域最广泛使用的静态分析工具。它能识别有问题的代码模式、强制执行编码规范,并在代码进入生产环境之前发现 Bug。随着 ESLint 9 和全新扁平配置系统的发布,该工具经历了自创建以来最重大的架构变革。无论你是在编写小型脚本还是维护大型 Monorepo,ESLint 都能帮助团队在每个文件中编写一致、高质量的代码。

TL;DR

ESLint 9 引入了扁平配置(eslint.config.js)取代旧的 .eslintrc 格式。它提供原生 TypeScript-ESLint 支持、React/Vue/Angular 框架插件、自定义规则编写、可共享配置、自动修复功能和深度 IDE 集成。扁平配置使用 JavaScript 模块实现完全的编程控制,简化了配置合并,消除了令人困惑的 extends/overrides 级联。

Key Takeaways
  • ESLint 9 扁平配置(eslint.config.js)用更简单、更可预测的基于 JavaScript 的配置系统取代了 .eslintrc。
  • TypeScript-ESLint 提供类型感知的 Lint 规则,能捕获 TypeScript 编译器无法检测到的错误。
  • ESLint 自动修复可以自动纠正许多问题,包括格式化、导入排序和代码风格违规。
  • 框架插件(React、Vue、Angular)为 Hooks、模板语法和生命周期模式添加组件特定规则。
  • 可共享配置让团队能够立即采用经过实战检验的规则集。
  • ESLint 负责代码检查,Prettier 负责格式化。Biome 提供一体化方案但插件生态较小。

什么是 ESLint 9 和扁平配置?

ESLint 是一个可插拔的 JavaScript 和 TypeScript 静态分析工具,它将源代码解析为抽象语法树(AST),然后运行一组规则进行检查。ESLint 9 是当前的主要版本,引入了扁平配置作为默认配置格式。

扁平配置用单个 eslint.config.js 文件取代了旧的 .eslintrc 格式,导出一个配置对象数组。每个对象指定适用的文件、启用的规则和加载的插件。配置对象从上到下合并,使解析逻辑透明且可预测。

# Install ESLint 9
npm init @eslint/config@latest

# Or install manually
npm install --save-dev eslint @eslint/js

# This creates eslint.config.js (flat config)
# No more .eslintrc.json, .eslintrc.yml, or .eslintrc.js

ESLint vs Prettier vs Biome

了解 ESLint 与 Prettier 和 Biome 的关系有助于为项目选择正确的工具组合。以下是它们核心能力的对比:

功能ESLintPrettierBiome
代码质量规则是(数百条)是(不断增长)
代码格式化有限(通过规则)是(固执己见)是(Prettier 兼容)
TypeScript 支持通过 typescript-eslint内置解析内置
自定义规则是(庞大生态)有限
速度中等非常快(Rust)
插件生态最大极少小但在增长
框架插件React、Vue、Angular、Svelte不适用React(部分)

2026 年最常见的配置是 ESLint 负责代码质量加上 Prettier 负责格式化。如果项目不依赖框架特定的 ESLint 插件,Biome 是一个优秀的一体化替代方案。

设置扁平配置(eslint.config.js)

扁平配置是 ESLint 9 中唯一支持的格式。配置文件导出一个配置对象数组。每个对象可以指定 files、ignores、plugins、rules、languageOptions 和 settings。

与旧格式不同,没有 extends 关键字。你将配置作为 JavaScript 模块导入并展开到数组中,消除了 .eslintrc 中令人困惑的 extends、overrides 和 env 级联。

// eslint.config.js - Basic flat config
import js from "@eslint/js";

export default [
  // Global ignores (like .eslintignore)
  {
    ignores: ["dist/", "build/", "node_modules/", "*.min.js"],
  },

  // ESLint recommended rules for all JS files
  js.configs.recommended,

  // Custom overrides
  {
    files: ["**/*.js", "**/*.mjs"],
    rules: {
      "no-unused-vars": "warn",
      "no-console": ["error", { allow: ["warn", "error"] }],
      "prefer-const": "error",
      "no-var": "error",
      eqeqeq: ["error", "always"],
    },
  },
];

规则和严重性级别

每条 ESLint 规则都有一个严重性级别来决定如何报告违规。理解这些级别对于有效配置项目至关重要。

  • "off"(或 0)- 完全禁用规则。Lint 过程中不运行该规则。 - undefined
  • "warn"(或 1)- 将违规报告为警告。Lint 过程成功退出。用于正在迁移的规则。 - undefined
  • "error"(或 2)- 将违规报告为错误。Lint 过程以非零代码退出。用于必须强制执行的规则。 - undefined

规则还可以接受配置选项数组。第一个元素是严重性,后续元素是规则特定设置。

// Rule configuration examples
export default [
  {
    rules: {
      // Severity only
      "no-debugger": "error",
      "no-alert": "warn",
      "no-eval": "off",

      // Severity + options
      "no-unused-vars": ["error", {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
        caughtErrorsIgnorePattern: "^_",
      }],

      // Numeric severity (0=off, 1=warn, 2=error)
      "no-console": [1, { allow: ["warn", "error", "info"] }],

      // Complex options
      "no-restricted-imports": ["error", {
        patterns: [{
          group: ["lodash"],
          message: "Import from lodash-es instead for tree-shaking.",
        }],
      }],
    },
  },
];

TypeScript-ESLint 集成

TypeScript-ESLint 是使 ESLint 能够检查 TypeScript 文件的官方工具。它提供 TypeScript 解析器、TypeScript 特定规则集和利用 TypeScript 编译器 API 进行更深层分析的类型感知规则。

类型感知规则是 TypeScript-ESLint 最强大的功能。它们使用完整的 TypeScript 类型系统检测 TypeScript 编译器和基本 Lint 规则无法捕获的问题。

// eslint.config.js - TypeScript-ESLint setup
import js from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
  js.configs.recommended,

  // Recommended type-checked rules
  ...tseslint.configs.recommendedTypeChecked,

  // Stylistic type-checked rules (optional)
  ...tseslint.configs.stylisticTypeChecked,

  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },

  // Custom TypeScript rules
  {
    files: ["**/*.ts", "**/*.tsx"],
    rules: {
      "@typescript-eslint/no-floating-promises": "error",
      "@typescript-eslint/no-misused-promises": "error",
      "@typescript-eslint/strict-boolean-expressions": "warn",
      "@typescript-eslint/no-unnecessary-condition": "error",
      "@typescript-eslint/prefer-nullish-coalescing": "error",
    },
  },

  // Disable type-aware rules for JS files
  {
    files: ["**/*.js", "**/*.mjs"],
    ...tseslint.configs.disableTypeChecked,
  },
);

React、Vue 和 Angular 插件

ESLint 为每个主要前端框架都有专门的插件。这些插件添加了理解框架特定模式的规则。

React 和 JSX

eslint-plugin-react 和 eslint-plugin-react-hooks 包为 React 组件和 Hooks 提供规则。Hooks 插件强制执行 Hooks 规则,这对避免函数组件中的微妙 Bug 至关重要。

// eslint.config.js - React + Hooks
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,

  {
    files: ["**/*.tsx", "**/*.jsx"],
    plugins: {
      react,
      "react-hooks": reactHooks,
    },
    languageOptions: {
      parserOptions: {
        ecmaFeatures: { jsx: true },
      },
    },
    rules: {
      ...react.configs.recommended.rules,
      ...reactHooks.configs.recommended.rules,
      "react/react-in-jsx-scope": "off",
      "react/prop-types": "off",
      "react-hooks/exhaustive-deps": "warn",
    },
    settings: {
      react: { version: "detect" },
    },
  },
];

Vue.js

eslint-plugin-vue 包为 Vue 单文件组件提供规则。它解析 template、script 和 style 部分并强制执行 Vue 特定约定。

// eslint.config.js - Vue 3
import js from "@eslint/js";
import vue from "eslint-plugin-vue";
import vueParser from "vue-eslint-parser";
import tseslint from "typescript-eslint";

export default [
  js.configs.recommended,
  ...vue.configs["flat/recommended"],

  {
    files: ["**/*.vue"],
    languageOptions: {
      parser: vueParser,
      parserOptions: {
        parser: tseslint.parser,
        sourceType: "module",
      },
    },
    rules: {
      "vue/multi-word-component-names": "warn",
      "vue/no-unused-vars": "error",
      "vue/require-default-prop": "error",
    },
  },
];

Angular

@angular-eslint 包取代 TSLint 成为 Angular 项目的官方 Lint 解决方案。它们为组件装饰器、依赖注入、模板语法和生命周期钩子提供规则。

// eslint.config.js - Angular
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import angular from "angular-eslint";

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommended,
  ...angular.configs.tsRecommended,

  {
    files: ["**/*.ts"],
    rules: {
      "@angular-eslint/directive-selector": ["error", {
        type: "attribute",
        prefix: "app",
        style: "camelCase",
      }],
      "@angular-eslint/component-selector": ["error", {
        type: "element",
        prefix: "app",
        style: "kebab-case",
      }],
    },
  },

  {
    files: ["**/*.html"],
    ...angular.configs.templateRecommended,
    ...angular.configs.templateAccessibility,
  },
);

编写自定义规则

ESLint 规则是接收 AST 节点和上下文对象的函数。上下文提供报告问题和访问设置的方法。自定义规则让你可以强制执行现有规则未涵盖的项目特定约定。

每条规则导出一个 meta 对象和一个 create 函数,create 返回一个将 AST 节点类型映射到处理函数的对象。

// eslint-plugin-custom/no-hardcoded-colors.js
export default {
  meta: {
    type: "suggestion",
    docs: {
      description: "Disallow hardcoded color hex values",
    },
    messages: {
      noHardcodedColor:
        "Avoid hardcoded color '{{ value }}'. Use a design token instead.",
    },
    schema: [],
  },

  create(context) {
    const HEX_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\$/;

    return {
      Literal(node) {
        if (
          typeof node.value === "string" &&
          HEX_PATTERN.test(node.value)
        ) {
          context.report({
            node,
            messageId: "noHardcodedColor",
            data: { value: node.value },
          });
        }
      },
    };
  },
};

// Using the custom rule in eslint.config.js
import noHardcodedColors from "./eslint-plugin-custom/no-hardcoded-colors.js";

export default [
  {
    plugins: {
      custom: { rules: { "no-hardcoded-colors": noHardcodedColors } },
    },
    rules: {
      "custom/no-hardcoded-colors": "warn",
    },
  },
];

可共享配置

可共享配置是导出 ESLint 配置数组的 npm 包。它们让团队无需手动配置数百条规则就能采用精选的规则集。

2026 年流行的可共享配置包括 @eslint/js、typescript-eslint 配置、@antfu/eslint-config 和 eslint-config-airbnb。

// eslint.config.js - Using @antfu/eslint-config
import antfu from "@antfu/eslint-config";

export default antfu({
  // Frameworks: auto-detected or manually enabled
  typescript: true,
  react: true,
  vue: false,

  // Formatting with Prettier-compatible style
  stylistic: {
    indent: 2,
    quotes: "single",
    semi: false,
  },

  // Override specific rules
  rules: {
    "no-console": "warn",
  },
});

// eslint.config.js - Composing multiple configs
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettierConfig from "eslint-config-prettier";

export default [
  js.configs.recommended,
  ...tseslint.configs.strict,
  prettierConfig,  // Must be last to override formatting rules
];

忽略文件和目录

在扁平配置中,使用配置对象的 ignores 属性来忽略文件。仅包含 ignores 的配置对象充当全局忽略模式,类似于旧的 .eslintignore 文件。

// eslint.config.js - Ignoring patterns
export default [
  // Global ignores (standalone object = .eslintignore equivalent)
  {
    ignores: [
      "dist/",
      "build/",
      "coverage/",
      "node_modules/",
      "*.min.js",
      "**/*.generated.ts",
      ".next/",
      "public/",
    ],
  },

  // Scoped ignores: exclude test fixtures from strict rules
  {
    files: ["**/*.ts"],
    ignores: ["**/__fixtures__/**", "**/__mocks__/**"],
    rules: {
      "@typescript-eslint/no-explicit-any": "error",
    },
  },
];

CLI 使用和常用命令

ESLint CLI 提供用于检查、修复、缓存和调试配置的命令。以下是日常开发中最常用的命令和标志。

# Lint all files in the project
npx eslint .

# Lint specific files or directories
npx eslint src/ tests/
npx eslint "src/**/*.{ts,tsx}"

# Auto-fix all fixable issues
npx eslint . --fix

# Enable caching for faster re-runs
npx eslint . --cache --cache-location .eslintcache

# Fail on warnings (useful in CI)
npx eslint . --max-warnings 0

# Show which config applies to a file
npx eslint --inspect-config

# Print timing info for rules (find slow rules)
TIMING=1 npx eslint .

# Output results as JSON
npx eslint . --format json --output-file report.json

# Common package.json scripts
# "lint": "eslint ."
# "lint:fix": "eslint . --fix"
# "lint:ci": "eslint . --cache --max-warnings 0"

IDE 集成(VS Code)

ESLint VS Code 扩展在你输入时提供实时 Lint 反馈。它内联显示错误和警告,提供快速修复操作,并可在保存时自动修复。

将以下设置添加到 VS Code settings.json 中,以获得 ESLint 保存时自动修复和 Prettier 格式化的最佳体验。

// .vscode/settings.json
{
  // Enable ESLint for these languages
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ],

  // Auto-fix ESLint issues on save
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },

  // Use Prettier as the default formatter
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,

  // ESLint uses flat config by default in v9
  // No additional setting needed for eslint.config.js
}

自动修复和格式化

ESLint 可以使用 --fix 标志自动修复许多规则违规。可修复的规则包括导入排序、未使用的禁用指令、间距问题和代码风格模式。

将 ESLint 与 Prettier 配合使用时,配置 eslint-config-prettier 关闭与 Prettier 格式化冲突的 ESLint 规则。

# Install Prettier + ESLint integration
npm install --save-dev prettier eslint-config-prettier

# eslint.config.js
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import prettierConfig from "eslint-config-prettier";

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,

  // prettier must be LAST to turn off conflicting rules
  prettierConfig,
];

# CI pipeline: run both
# Step 1: Check formatting
# npx prettier --check .
# Step 2: Check code quality
# npx eslint . --max-warnings 0

从 .eslintrc 迁移到扁平配置

ESLint 提供迁移工具和兼容性工具帮助团队从旧的 .eslintrc 格式过渡到扁平配置。@eslint/eslintrc 包提供 FlatCompat 类来包装旧配置。

要进行干净的迁移,先运行 ESLint 配置迁移工具,然后逐步将 FlatCompat 包装器替换为原生扁平配置。

# Step 1: Run the migration tool
npx @eslint/migrate-config .eslintrc.json

# This generates eslint.config.mjs with FlatCompat wrappers
# for any legacy plugins that do not support flat config yet.

# Step 2: Example generated config with FlatCompat
# import { FlatCompat } from "@eslint/eslintrc";
# import path from "node:path";
# import { fileURLToPath } from "node:url";
#
# const __filename = fileURLToPath(import.meta.url);
# const __dirname = path.dirname(__filename);
# const compat = new FlatCompat({ baseDirectory: __dirname });
#
# export default [
#   ...compat.extends("eslint-config-airbnb"),
#   { rules: { "no-console": "warn" } },
# ];

# Step 3: Gradually replace FlatCompat with native imports
# as plugins release flat-config-compatible versions.
# Delete .eslintrc.json and .eslintignore when done.

Monorepo 配置

在 Monorepo 中,通常有一个定义共享规则的根 eslint.config.js,加上包特定的覆盖。扁平配置使这变得简单,因为你可以从不同包导入和组合配置数组。

每个工作区包可以导出自己的配置片段,根配置导入并合并它们。

// eslint.config.js - Monorepo root config
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";

export default [
  // Global ignores
  { ignores: ["**/dist/", "**/node_modules/", "**/.next/"] },

  // Shared base rules for all packages
  js.configs.recommended,
  ...tseslint.configs.recommended,

  // Frontend: React rules
  {
    files: ["packages/web/**/*.tsx", "packages/web/**/*.ts"],
    plugins: { react, "react-hooks": reactHooks },
    rules: {
      ...react.configs.recommended.rules,
      ...reactHooks.configs.recommended.rules,
      "react/react-in-jsx-scope": "off",
    },
    settings: { react: { version: "detect" } },
  },

  // Backend: Node.js rules
  {
    files: ["packages/api/**/*.ts"],
    rules: {
      "no-console": "off",
    },
  },

  // Tests: relaxed rules
  {
    files: ["**/*.test.ts", "**/*.spec.ts"],
    rules: {
      "@typescript-eslint/no-explicit-any": "off",
      "@typescript-eslint/no-non-null-assertion": "off",
    },
  },
];

性能优化

ESLint 在大型代码库上可能较慢,尤其是使用类型感知 TypeScript 规则时。以下技术可以显著减少 Lint 时间。

  • 启用 --cache 标志跳过未更改文件的重新检查。
  • 使用 typescript-eslint 的项目引用限制 Monorepo 中每个包的类型检查范围。
  • 使用全局 ignores 排除生成的文件、构建输出和 node_modules。
  • 如果性能成本大于收益,对测试文件禁用类型感知规则。
  • 使用 eslint-plugin-import 并启用解析器缓存。
  • 使用 turbo lint 或 nx lint 等工具跨工作区并行运行 ESLint。
  • 固定特定规则集而非使用启用所有规则的 "all" 配置。
  • 使用 TIMING=1 npx eslint 分析慢规则。

最佳实践

遵循以下建议从 ESLint 中获得最大价值。

  • 从推荐配置开始定制,而不是从头构建。
  • 将 ESLint 错误视为 CI 阻断器。警告应该是临时的。
  • ESLint 负责代码质量,Prettier 负责格式化。配置 Prettier 时不要使用 ESLint 格式化规则。
  • 用注释组织扁平配置文件,分隔基础规则、TypeScript 规则、框架规则和测试覆盖。
  • 固定 ESLint 和插件版本。主版本升级可能改变规则行为。
  • 谨慎使用 eslint-disable 注释。每条都应包含解释原因。
  • 配置编辑器保存时自动修复,立即捕获问题。
  • 在 CI 管道中使用 --max-warnings 0 防止警告积累。
  • 每次主要版本发布时审查新规则。
  • 在项目文档中记录自定义规则或非显而易见的配置选择。

常见问题

什么是 ESLint 扁平配置?

扁平配置是 ESLint 9 引入的新配置格式。它使用单个 eslint.config.js 文件导出配置对象数组。配置从上到下合并,取代了旧 .eslintrc 格式复杂的 extends/overrides 级联。

如何将 ESLint 与 TypeScript 一起使用?

安装 typescript-eslint 并在 eslint.config.js 中配置。使用 tseslint.config() 辅助函数提供推荐和严格规则预设。类型感知规则使用 TypeScript 编译器 API 进行更深层分析。

应该使用 ESLint 还是 Prettier?

两者都用。ESLint 处理代码质量规则,Prettier 处理格式化。安装 eslint-config-prettier 禁用冲突的规则。

如何从 .eslintrc 迁移到扁平配置?

运行 npx @eslint/migrate-config .eslintrc.json 生成扁平配置文件。逐步将 FlatCompat 包装器替换为原生扁平配置导入。

ESLint 和 Biome 有什么区别?

ESLint 是基于 JavaScript 的 Lint 工具,拥有最大的插件生态。Biome 是基于 Rust 的工具链,将 Lint 和格式化合二为一。Biome 更快但规则更少,框架插件支持有限。

如何自动修复 ESLint 错误?

运行 eslint --fix 自动修复所有可修复的违规。在 VS Code 中启用保存时自动修复。并非所有规则都可自动修复。

如何为 Monorepo 配置 ESLint?

在根目录放置 eslint.config.js 定义共享规则,使用 files 属性为特定包应用覆盖。Turborepo 和 Nx 可以跨工作区并行运行 ESLint。

如何提升 ESLint 性能?

启用 --cache 缓存,排除生成文件,限制类型感知规则范围,使用 TIMING=1 分析慢规则。在 Monorepo 中使用项目引用限制类型检查范围。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON FormatterJSJavaScript Minifier.*Regex Tester

相关文章

Vitest 完全指南:现代 JavaScript/TypeScript 快速单元测试 (2026)

完整的 Vitest 指南,涵盖安装配置、测试语法、Mock、快照测试、代码覆盖率、Vue/React 组件测试、TypeScript 集成、Vitest UI 和从 Jest 迁移。

TypeScript 类型守卫:运行时类型检查完全指南

掌握 TypeScript 类型守卫:typeof、instanceof、in、自定义类型守卫和可辨识联合。

React 设计模式指南:复合组件、自定义 Hook、HOC、Render Props 与状态机

完整的 React 设计模式指南,涵盖复合组件、render props、自定义 hooks、高阶组件、Provider 模式、状态机、受控与非受控、组合模式、观察者模式、错误边界和模块模式。