eslint匹配规则速通

eslint匹配规则速通

匹配规则

在 eslint.config.js 里,"当前文件" 到底会被哪一个(或哪几个)配置对象命中,是按下述流程逐条计算的。 只要记住一句话:

ESLint 会把文件路径依次跟每个配置对象的 files/ignores 做 glob 匹配,命中且未被忽略的就生效;多个对象都命中就层层合并。

下面把"匹配"这件事拆成 5 个具体问题,一次性讲透。


  1. 拿谁来匹配? 文件在磁盘里的绝对路径 (Windows 带盘符,Unix 以 / 开头)。 例: /home/me/proj/src/utils/is-empty.js D:\repo\src\utils\is-empty.js

  2. 跟谁匹配? 每个配置对象里可能出现的两组 glob 模式:

    • files 数组 ------ 白名单
    • ignores 数组 ------ 黑名单(支持 ! 否定)
  3. 匹配顺序(级联) 对每一个配置对象:

    1. 若对象没有 files,视为 files:["**/*"](全选)。
    2. 拿文件路径去跟 files 里每一项做 minimatch(类 .gitignore 语法)。
      • 只要有一项命中就认为该对象"适用于"此文件。
    3. 若对象还有 ignores,再跟这些模式比对:
      • 命中任何 ignores 就立即把该对象排除,不再参与后续合并。
      • 支持否定写法 "!xxx",可再把文件"捞回来"。
    4. 全局忽略规则(对象里只有 ignores,没有 files 等其他键)会在所有对象之前先算一次,原理相同。
  4. 合并结果 经过上面筛选后,可能 0 ~ N 个对象对当前文件生效。

    • 0 个 → ESLint 报错 "No configuration provided for ..."
    • ≥1 个 → 按数组顺序浅合并 (靠后的覆盖靠前的): languageOptions/linterOptions/plugins/settings 递归合并; rules 直接覆盖同名键。
  5. 快速验证 命令行看一眼到底哪条配置命中:

    bash 复制代码
    npx eslint --inspect-config src/utils/is-empty.js

    会打印出最终合并后的完整配置以及"来自哪几个对象",调试神器。

js 复制代码
export default [
  {                           // 对象 A
    ignores: ["**/*.config.js"]   // 全局忽略
  },
  {                           // 对象 B
    files: ["src/**/*.js"],
    ignores: ["**/*.test.js"],
    rules: { semi: "warn" }
  },
  {                           // 对象 C
    files: ["**/*.test.js"],
    rules: { semi: "off" }
  }
]

现在 lint 文件 /proj/src/utils/is-empty.js

  1. 全局忽略 A 先算 ------ 文件名不是 *.config.js,未被忽略,继续。
  2. 对象 B:files 命中 src/**/*.js,且不在 ignores 里 → 生效。
  3. 对象 C:files 命中 **/*.test.js,但当前文件不是测试 → 跳过。

最终只有 B 生效,semi: "warn"。

再把 /proj/src/utils/is-empty.test.js 走一遍:

  1. 全局忽略 A 同上,未忽略。
  2. 对象 B:虽然命中 src/**/*.js,但紧接着被 **/*.test.js 忽略 → 对象 B 被排除。
  3. 对象 C:命中 **/*.test.js → 生效 ,semi: "off"。

合并规则

flat Config 的"合并"并不是深度合并(deep merge),而是按数组顺序、一级一级地"覆盖 + 累加",规则非常干脆:

  1. 数组顺序 = 优先级 后出现的 config 对象如果和前面的同字段同名 ,就整值覆盖;不同名就累加。
  2. 命中范围(files / ignores)独立判断 对单个文件来说,ESLint 会把所有路径命中 的 config 对象收集起来,再按顺序合并; 只要某一段 config 的 ignores 匹配了,这段及后面同路径的 config 就被整段跳过。
  3. 合并粒度只到"字段"一级
    • languageOptions、plugins、rules 都是整对象替换,不会递归合并内部子键。
    • 想"增量"就必须把前面那段再抄一遍,或者利用展开运算符自己拼装。

看一段代码就懂

js 复制代码
export default [
  {                                                    // ①
    files: ['**/*.ts'],
    languageOptions: { parser: ts.parser, ecmaVersion: 2022 },
    rules: { '@typescript-eslint/no-explicit-any': 'warn', 'no-console': 'off' }
  },
  {                                                    // ②
    files: ['**/*.ts'],
    rules: { 'no-console': 'error' }                   // 整对象覆盖,结果只剩 no-console:error
  }
];

对任意 .ts 文件:

  • 先收集 ① → 再收集 ②
  • ② 的 rules 是全新对象,直接把 ① 的 rules 整份替换掉;languageOptions 保留 ① 的,因为 ② 没写。

最终生效的只有:

js 复制代码
languageOptions: { parser: ts.parser, ecmaVersion: 2022 }
rules: { 'no-console': 'error' }

@typescript-eslint/no-explicit-any 这条规则被"覆盖没"了------不会自动保留。

相关推荐
子兮曰3 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
sm_926787056 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
IMPYLH7 小时前
HTML 的 <video> 元素
前端·html
溪语流沙7 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
逐光者9337 小时前
STM32——SPI 屏 · Flash · 高速
java·前端·stm32
To_OC7 小时前
同样是让 AI 写全栈,为什么别人一句话就够了
前端·前端框架·next.js
CDwenhuohuo8 小时前
electron pc项目打包成桌面端
前端·javascript·electron
前端大斗师8 小时前
「大于 1000」把 1000 元那单也算进去了:我在 Vue3 订单页对了 10 句话
前端·人工智能·typescript·大模型·原力计划
Jmyd01238 小时前
用 Web VR 引擎搭建 3D 虚拟展厅:从素材上云到多端实时渲染的完整数据链路
前端·3d·vr·三维数字化
刘天远9 小时前
Agent成本核算实现:事件表、状态分布与Python归集
前端·数据库·人工智能·python