关于 shared-tooling-eslint-prettier
为使用 ESLint 与 Prettier 的开发者提供配置实践指南,涵盖 ESLint 扁平配置、TypeScript 类型检查及团队共享配置。强调 lint 与格式化职责分离,并减少规则冲突。
主要功能
- 01ESLint 9+ 扁平配置
- 02globalIgnores 全局忽略规则
- 03typescript-eslint projectService
- 04共享团队配置
- 05Prettier 格式化配置
- 06自定义 ESLint 规则
适用场景
- 01为新项目设置 lint 和格式化
- 02将旧版 .eslintrc 迁移到扁平配置
- 03统一单体仓库中的代码规范
- 04配置 TypeScript 类型感知 lint
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents-inc/ skills --skill shared-tooling-eslint-prettier安装后在 Claude Code 中输入/shared-tooling-eslint-prettier确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.yamlreference.mdexamples/core.mdeslint.mdprettier.md详细介绍
ESLint 与 Prettier
**快速指南:**使用 ESLint 9+ 扁平配置,配合
defineConfig()和globalIgnores()。使用带有projectService: true的 typescript-eslint v8+。使用统一格式的 Prettier 共享配置。使用 eslint-config-prettier 禁用冲突规则。使用 eslint-plugin-only-warn,提升开发体验(DX)。警告:ESLint 10 于 2026 年 2 月发布,并彻底移除了对 .eslintrc 的支持。请立即迁移到扁平配置。
<critical_requirements>
关键:使用此技能前
(必须使用来自 eslint/config 的 defineConfig(),采用 ESLint 9+ 扁平配置——不要使用旧版 .eslintrc)
(必须使用 globalIgnores() 明确指定全局忽略模式——不要使用单独的 ignores 属性)
(必须使用带有 projectService: true 的 typescript-eslint v8+ 进行类型化 lint)
(必须包含 eslint-plugin-only-warn,将错误转换为警告,以提升开发体验(DX))
(必须使用 eslint-config-prettier 禁用与 Prettier 冲突的格式规则)
</critical_requirements>
**自动检测:**ESLint 9 扁平配置、defineConfig、globalIgnores、eslint.config.ts、Prettier 配置、prettier.config.mjs、eslint-config-prettier、eslint-plugin-only-warn、typescript-eslint projectService、.eslintrc 迁移
适用场景:
- 设置 ESLint 9/10 扁平配置(独立配置或共享配置)
- 使用共享配置配置 Prettier
- 从旧版 .eslintrc 迁移到扁平配置
- 集成 ESLint 与 Prettier(eslint-config-prettier)
- 配置带有 projectService 的 typescript-eslint v8+
- 设置自定义 ESLint 规则(命名导出、导入限制、类型导入)
不适用场景:
- 运行时代码(这仅用于构建时工具)
- CI/CD 流水线配置
- Git 钩子或 lint-staged 设置
- TypeScript 编译器配置(tsconfig)
- 打包工具配置
详细资源:
- examples/core.md - 基本的扁平配置与 Prettier 设置
- examples/eslint.md - 高级 ESLint 模式(共享配置、自定义规则、ESLint 10 迁移)
- examples/prettier.md - 高级 Prettier 模式(TS 配置、实验性选项、忽略文件)
- reference.md - 版本参考与官方文档链接
理念
Lint 和格式化应当快速、一致且不会阻塞工作。开发者不应与工具对抗——工具应帮助及早发现问题,同时避免干扰开发过程。
核心原则:
- 用警告,而非错误 - 使用 only-warn 将 lint 错误转换为警告,让开发者可以迭代而不受阻碍
- 单一事实来源 - 共享配置可避免不同软件包和团队成员之间出现偏差
- 自动格式化 - 由 Prettier 处理所有格式决策;ESLint 只负责代码质量
- 避免冲突 - eslint-config-prettier 确保 ESLint 与 Prettier 始终保持一致
核心模式
模式 1:使用 defineConfig() 的 ESLint 9+ 扁平配置
ESLint 9+ 使用扁平配置。来自 eslint/config 的 defineConfig() 助手函数可提供类型安全并自动展平数组。globalIgnores() 可明确标记全局忽略模式。
// eslint.config.ts — the essential flat config
import js from "@eslint/js";
import { defineConfig, globalIgnores } from "eslint/config";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import * as onlyWarnPlugin from "eslint-plugin-only-warn";
export default defineConfig(
globalIgnores(["dist/**", "generated/**", "node_modules/**"]),
js.configs.recommended,
eslintConfigPrettier,
tseslint.configs.recommended,
{ plugins: { "only-warn": onlyWarnPlugin } }, // must be last
);
要点:defineConfig() 会自动展平数组(无需展开运算符),globalIgnores() 可避免单独使用 ignores 时的行为不明确,only-warn 会将此前所有错误转换为警告,eslint-config-prettier 会禁用与 Prettier 冲突的格式规则。
完整的独立配置和共享配置模式请参阅 examples/core.md。
### 模式 2:搭配 projectService 使用 typescript-eslint v8+
projectService 功能自 v8 起已稳定,可为每个文件自动查找最近的 tsconfig.json,取代容易出问题的手动 project 路径。
parserOptions: {
projectService: true,
allowDefaultProject: ["*.config.ts", "*.config.mjs"],
},
要点: 无需 tsconfig.eslint.json 文件;比手动配置项目更快;allowDefaultProject 可处理不在 tsconfig 中的配置文件。
完整的 typescript-eslint 配置请参阅 examples/core.md。
模式 3:共享配置模式(Monorepo/团队)
对于团队或 Monorepo,可将 lint 配置提取到共享包中,以避免配置偏差。
// packages/eslint-config/base.ts — shared config
export const baseConfig = defineConfig(
globalIgnores(["dist/**", "generated/**"]),
js.configs.recommended,
eslintConfigPrettier,
tseslint.configs.recommended,
{ plugins: { "only-warn": onlyWarnPlugin } },
);
// apps/my-app/eslint.config.ts — consuming shared config
export default defineConfig(baseConfig, customRules, {
rules: { "no-console": "warn" },
});
要点: defineConfig() 会自动扁平化,因此无需使用展开运算符;单一可信来源可避免配置偏差;使用 TypeScript 配置文件进行类型检查。
共享配置和自定义规则模式请参阅 examples/eslint.md。
模式 4:Prettier 共享配置
所有包的 Prettier 配置都应保持一致。团队可使用共享配置。
// prettier.config.mjs
const config = {
printWidth: 100,
semi: true,
singleQuote: false,
bracketSpacing: true,
arrowParens: "always",
endOfLine: "lf",
bracketSameLine: false,
// trailingComma: "all" is the default in Prettier 3.0+
};
export default config;
要点: v3.0+ 中 trailingComma: "all" 是默认值(无需显式设置);bracketSameLine 取代了已弃用的 jsxBracketSameLine;显式设置 endOfLine: "lf" 可避免跨平台问题。
TypeScript 配置文件、实验性选项和忽略模式请参阅 examples/prettier.md。
模式 5:自定义 ESLint 规则
用于执行项目约定的常见自定义规则——命名导出、统一类型导入、未使用变量检测,以及导入边界限制:
export const customRules = {
rules: {
"import/no-default-export": "warn",
"@typescript-eslint/consistent-type-imports": [
"warn",
{ prefer: "type-imports" },
],
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
},
};
包含导入边界限制在内的完整自定义规则模式请参阅 examples/eslint.md。
模式 6:使用 extends 属性(ESLint 9.15+)
扁平配置对象中的 extends 属性可简化插件组合——无论插件格式(对象、数组或字符串)如何,都能统一配置合并方式:
export default defineConfig({
files: ["**/*.ts", "**/*.tsx"],
extends: [
"eslint/recommended",
tseslint.configs.recommended,
// Add your framework plugin's flat config here
],
rules: { "no-console": "warn" },
});
完整的 extends 模式请参阅 examples/core.md。
<decision_framework>
决策框架
ESLint + Prettier 与替代方案对比
Need linting and formatting?
├─ Speed is critical bottleneck (1000+ files)?
│ └─ YES → Consider a Rust-based unified linter/formatter (not this skill's scope)
└─ Need mature plugin ecosystem?
└─ YES → ESLint 9/10 + Prettier ✓
ESLint + Prettier 的优势: 生态成熟、插件支持广泛、提供针对框架的插件
ESLint 9 与 ESLint 10
Which ESLint version?
├─ New project?
│ └─ ESLint 10 (latest, cleanest API)
├─ Existing project with flat config?
│ └─ ESLint 10 (straightforward upgrade)
├─ Existing project with .eslintrc?
│ ├─ Can invest time to migrate?
│ │ └─ YES → Migrate to flat config, then ESLint 10
│ └─ NO → ESLint 9.x (still supported, but plan migration)
└─ Node.js < 20.19.0?
└─ ESLint 9.x (ESLint 10 requires 20.19.0+)
共享配置与本地配置
Setting up linting/formatting?
├─ Monorepo with multiple packages?
│ └─ YES → Shared config ✓
├─ Team project (2+ developers)?
│ └─ YES → Shared config (consistency matters)
└─ Single package / solo project?
└─ YES → Local config is fine
Prettier 配置文件格式
What Prettier config format to use?
├─ Need type checking in config?
│ ├─ Node.js 22.6.0+? → prettier.config.ts
│ └─ NO → Use .mjs with JSDoc types
├─ ESM project? → prettier.config.mjs
└─ CommonJS project? → prettier.config.cjs
</decision_framework>
<red_flags>
风险信号
高优先级问题:
- ❌ 使用旧版 .eslintrc 格式,而非 ESLint 9+ 扁平配置(在 ESLint 10 中无法使用)
- ❌ 使用裸
ignores属性,而非globalIgnores()助手(行为模糊——单独使用时会作为全局忽略规则,但与其他属性搭配时会作为局部排除规则) - ❌ 缺少 eslint-plugin-only-warn(错误会在开发过程中阻塞开发者)
- ❌ 缺少 eslint-config-prettier(ESLint 和 Prettier 规则冲突,导致无休止的修复循环)
中优先级问题:
- ⚠️ 在 typescript-eslint 中手动使用
project选项,而非projectService: true(在 monorepo 中不可靠,速度较慢) - ⚠️ 在 Prettier 中使用已弃用的
jsxBracketSameLine选项(在 Prettier 2.4 中更名为bracketSameLine) - ⚠️ 在 Prettier 3.0+ 中显式设置
trailingComma: "all"(它已经是默认值) - ⚠️ 使用
tseslint.config()包装器(计划弃用,改用 ESLint 原生的defineConfig()) - ⚠️ 在各个包中硬编码配置值,而非使用共享配置
易错点和边缘情况:
- only-warn 插件必须在其他插件之后加载,才能将它们的错误转换为警告
defineConfig()会自动扁平化数组——切勿与它搭配使用展开运算符projectService需要 typescript-eslint v8+(在 v6-v7 中名为EXPERIMENTAL_useProjectService)- ESLint 10 要求 Node.js
^20.19.0 || ^22.13.0 || >=24(明确不支持 v21.x 和 v23.x) - ESLint 10 的配置查找从被 lint 文件所在的目录开始(而非 cwd)——支持 monorepo 多配置
- Prettier TypeScript 配置文件(
.prettierrc.ts)要求 Node.js 22.6.0+;在 Node v24.3.0 之前运行时需添加--experimental-strip-types - Prettier 3.0+ 的 API 为异步;使用同步 API 的插件需要迁移(同步包装器可使用
@prettier/sync) - ESLint 9.15+:原生支持
eslint.config.tsTypeScript 配置文件和extends属性 - ESLint 9.34+:可通过
--concurrency标志启用多线程 lint(大型项目的性能提升 30-300%) - ESLint 10:
/* eslint-env */注释现在会触发错误;已移除弃用的Linter方法
</red_flags>
<critical_reminders>
重要提醒
(必须使用 ESLint 9+ 扁平配置,并从 eslint/config 导入 defineConfig()——不得使用旧版 .eslintrc)
(必须使用 globalIgnores() 指定显式的全局忽略模式——不得使用裸 ignores 属性)
(必须使用 typescript-eslint v8+,并通过 projectService: true 执行类型检查 lint)
(必须包含 eslint-plugin-only-warn,以便将错误转换为警告,改善开发体验)
(必须使用 eslint-config-prettier,禁用与 Prettier 冲突的格式规则)
不遵循这些规则会导致工具配置不一致、格式规则冲突,并阻塞开发者。
警告:ESLint 10(2026 年 2 月)将彻底移除对 .eslintrc 的支持。请立即规划迁移。
</critical_reminders>