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. 合并粒度只到"字段"一级
    • languageOptionspluginsrules 都是整对象替换,不会递归合并内部子键。
    • 想"增量"就必须把前面那段再抄一遍,或者利用展开运算符自己拼装。

看一段代码就懂

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 这条规则被"覆盖没"了------不会自动保留

相关推荐
Zyx20072 小时前
用 Vue 3 构建任务清单:响应式编程的优雅实践
前端
风止何安啊2 小时前
那些让你 debug 到凌晨的陷阱,我帮你踩平了:React Hooks 避坑指南
前端·react.js·面试
用户279656042702 小时前
wx微信小程序部分逻辑
前端
大大花猫2 小时前
我用AI写了个小程序,却被人说没有底线…
前端·微信小程序·交互设计
梵尔纳多2 小时前
打包 Electron 程序
前端·javascript·electron
接着奏乐接着舞。2 小时前
3D地球可视化教程 - 第6篇:蜂巢网格与自定义几何体
前端·vue.js·3d·threejs
GISer_Jing2 小时前
Taro打造电商项目实战
前端·javascript·人工智能·aigc·taro
KLW752 小时前
vue watch监听
前端·javascript·vue.js
晴殇i2 小时前
🎉 TRAE 一年使用的过程体验 🎉
前端