
eslint-plugin-unicorn 的 consistent-compound-words 规则统一标识符中复合词拼写的完整指南【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇指南以 eslint-plugin-unicorn 仓库中consistent-compound-words规则为主线系统讲解该规则如何统一标识符中复合词的拼写风格、内置的 52 组默认替换词表、全部 8 个可配置选项replacements、allowList、checkProperties等以及底层的正则匹配与安全重命名实现原理。读完本文你将能够在自己的 ESLint 配置中精准启用、定制并理解这条规则从而让代码库中passWord/password、userName/username这类写法不一致的问题被自动发现并一键修复。规则是什么为什么复合词拼写需要被约束在遵循 camelCase 等标识符命名规范的代码库中同一个复合词往往会被不同开发者写成不同形态有人写passWord有人写password有人写isInViewPort有人写isInViewport。这些写法在 JavaScript 语义上完全等价但会导致同一概念在代码中出现多种大小写形态破坏检索一致性、增加心智负担。consistent-compound-words规则的职责正是解决这个问题把复合词当作一个整体来套用标识符大小写约定从而保证同一复合词在全部标识符中拼写一致。该规则文档位于 docs/rules/consistent-compound-words.md其实现位于 rules/consistent-compound-words.js。需要特别强调的是这条规则不是拼写检查器也不是散文风格规则——它只针对一份保守精选的、代码标识符中常见的复合词拼写错误清单进行检查避免误伤正常命名。基本示例// ❌ 错误passWord 应为 password const passWord secret; // ✅ 正确 const password secret;// ❌ 错误ViewPort 应作为一个整体单词 const isInViewPort true; // ✅ 正确 const isInViewport true;// ❌ 错误unSubscribe 应为 unsubscribe function unSubscribe() {} // ✅ 正确 function unsubscribe() {}从源码的 meta 定义可见该规则类型为suggestionrecommended级别为unopinionated并且hasSuggestions: true意味着它可以通过编辑器建议editor suggestions手动修复即不需要--fix也会在编辑器中给出可点击的一次性重命名建议rules/consistent-compound-words.js。同时该规则已启用在上文文档头部声明的recommended与unopinionated两套预设配置中对应 configs/flat-config-base.js 等配置文件所导出的规则集。内置默认替换词表一份保守的复合词清单规则的全部默认替换映射定义在源码的defaultReplacements对象中rules/consistent-compound-words.js。下表完整列出默认检查的 52 组词被禁止写法→推荐写法禁止写法推荐写法禁止写法推荐写法backGroundbackgroundsideBarsidebarcallBackcallbacksubClasssubclasscheckBoxcheckboxsubDirectorysubdirectoryclipBoardclipboardsubDomainsubdomaincodeBasecodebasesubMenusubmenudataBasedatabasesubProcesssubprocessdownLoaddownloadsubStringsubstringfeedBackfeedbacksubTreesubtreeforeGroundforegroundsubTypesubtypeframeWorkframeworksubTitlesubtitleheadLineheadlinetimeOuttimeoutkeyBoardkeyboardtimeStamptimestampkeyFramekeyframetoolBartoolbarlifeCyclelifecycletoolKittoolkitmetaDatametadatatoolTiptooltipmidPointmidpointtouchScreentouchscreennameSpacenamespaceunSubscribeunsubscribeoverRideoverrideunderScoreunderscorepassWordpasswordupLoaduploadpayLoadpayloaduserNameusernameplaceHolderplaceholderviewPortviewportpreViewpreviewwebCamwebcamscreenShotscreenshotwebHookwebhookwhiteSpacewhitespacewebSitewebsitewildCardwildcardweekEndweekendworkFlowworkflowworkSpaceworkspace匹配的大小写适应性该规则对大小写是自适应的上述词表以驼峰形态给出但匹配时同时考虑小写首字母形态与大写首字母形态。根据源码中的注释rules/consistent-compound-words.js小写首字母形态只匹配标识符开头而大写首字母形态可以匹配标识符的任意复合段。这意味着passWord、myPassWord、passWordAndUserName都会被命中测试用例见 test/consistent-compound-words.js类名ViewPortState、class ViewPort {}也会被报告替换时会把ViewPort段替换为Viewport全大写常量VIEW_PORT不会被检查源码getNameReplacement中显式跳过isUpperCase(name)见 rules/consistent-compound-words.js因为全大写形态本身就是对复合词的可接受表达。单词边界的判断规则不是简单子串替换。匹配使用了一个精心构造的边界正则(?$|[\d_$]|\p{Uppercase_Letter})rules/consistent-compound-words.js保证只命中“真正的复合词段”。因此测试中以下命名都被判定为合法foo_userName、version2userName——下划线和数字会打断匹配compassWord、myViewPortion、endPoint、postFix、preFix、protoType、roadMap——这些并不是清单中的禁止写法只是形似XMLHttpRequest——全大写形态被跳过。以上合法用例均可在 test/consistent-compound-words.js 的 valid 列表中核对。刻意不检查的内容保护外部 API 面规则文档专门用一节说明“Intentionally not checked”docs/rules/consistent-compound-words.md这一点在源码与测试中有完整印证字符串键、计算属性、属性读取、JSX 属性、导出别名不检查。它们往往是外部 API 表面保持原拼写比强行规范化更重要。例如const options {timeOut: 1000}、foo[timeOut] 1、input passWordcurrent /均合法export {username as userName}也不会被报告见 test/consistent-compound-words.js 与 test/consistent-compound-words.js 的 JSX 用例。歧义或常见 API 拼写被显式排除如fileName、setUp、lookUp、newLine以及源码注释中点名的onLine、offLine、styleSheet、superClassrules/consistent-compound-words.js。这些词在“各词保持独立含义”的场景下是自然标识符——例如“一个新创建的行”而不是“换行符”。测试中const newLine \n、navigator.onLine isOnline、document.styleSheet styleSheet、class Foo { superClass Base; }均为合法见 valid 用例列表。完整选项指南规则接受一个对象作为第二参数全部选项及默认值如下对应源码prepareOptions与 schema 定义见 rules/consistent-compound-words.js 和 rules/consistent-compound-words.jsreplacementsobject默认{}在默认替换表的基础上扩展自定义替换。值为false可以显式禁用某个默认替换值为字符串则是自定义的“禁止写法 → 推荐写法”映射unicorn/consistent-compound-words: [ error, { replacements: { fooBar: foobar, passWord: false, // 禁用内置的 passWord → password }, }, ]注意 schema 约束键名长度至少为 1值必须是长度至少为 1 的字符串或falserules/consistent-compound-words.js。测试中也覆盖了自定义替换的验证test/consistent-compound-words.js。extendDefaultReplacementsboolean默认true当设为false时replacements将完全覆盖默认替换表而不是扩展unicorn/consistent-compound-words: [ error, { extendDefaultReplacements: false, replacements: { fooBar: foobar, }, }, ]该逻辑在源码中体现为extendDefaultReplacements ? {...defaultReplacements, ...replacements} : replacementsrules/consistent-compound-words.js。allowListobject默认{}按大小写精确跳过整个标识符名称值必须是true。适用于希望在个别位置保留历史命名的场景unicorn/consistent-compound-words: [ error, { allowList: { legacyUserName: true, }, }, ]允许列表在源码中转换为Set并参与getNameReplacement的前置判断rules/consistent-compound-words.js 与 rules/consistent-compound-words.js。schema 强制其值必须为truerules/consistent-compound-words.js测试中allowList: {userName: false}会触发校验错误test/consistent-compound-words.js。checkVariablesboolean默认true是否检查变量名。设为false可关闭对变量包括函数名、类名等绑定标识符的检查只保留属性检查能力配合checkProperties使用unicorn/consistent-compound-words: [ error, { checkVariables: false, checkProperties: true, }, ]源码中变量检查在Program:exit阶段基于 scope 变量统一进行rules/consistent-compound-words.js。checkPropertiesboolean默认false设为true后将检查属性定义与属性写入。源码中reportProperty通过Identifier与PrivateIdentifier事件处理rules/consistent-compound-words.js具体覆盖属性写入foo.userName 1、foo.userName、foo.userName对象字面量属性({passWord: 1})非简写形式类成员与 TypeScript 声明类字段viewPort、私有字段#passWord、interface/type成员、accessor、抽象成员等见 TypeScript 测试组 test/consistent-compound-words.js特别地__proto__与ExportSpecifier会被跳过rules/consistent-compound-words.js。checkDefaultAndNamespaceImportsinternal | boolean默认internal控制默认导入与命名空间导入含静态require()的变量名是否检查internal默认只检查指向内部模块的导入即模块路径以.或/开头且不包含node_modules判断逻辑见 rules/shared/identifier-checks.js。因此import userName from user-name外部包默认合法而import userName from ./user-name.js会被报告true所有默认/命名空间导入都检查import userName from user-name也会被报告见 test/consistent-compound-words.jsfalse完全不检查这类导入变量。checkShorthandImportsinternal | boolean默认internal与上一项对称控制简写导入import {userName} from ...的本地绑定名是否检查。internal同样只检查内部模块的简写导入rules/shared/identifier-checks.js。测试中import {userName} from user-name默认合法开启checkShorthandImports: true后会被报告。checkShorthandPropertiesboolean默认false设为true后检查对象解构模式中作为简写属性声明的变量例如const {userName} object中的userName。默认关闭是因为简写属性同时是变量声明其重命名会影响外部契约源码中通过isShorthandPropertyValue判断rules/consistent-compound-words.js。选项合法性校验规则的 JSON schema 对上述选项做了严格约束不允许出现未声明属性如extendDefaultAllowList会直接报错、checkDefaultAndNamespaceImports/checkShorthandImports只能是internal或布尔值、replacements的键名和值均有最小长度要求、allowList的值必须为true。这些约束都有对应的 schema 校验测试兜底test/consistent-compound-words.js。底层原理单次正则扫描与安全重命名合并正则一次扫描全部词表规则将每个禁止写法生成小写首字母与大写首字母两种形态并把它们合并到一个正则中buildReplacementRegExprules/consistent-compound-words.js。源码注释解释了这样做的动机如果不合并规则就要为每个替换词、对文件里每个标识符分别编译并执行一次正则性能开销巨大合并后每个标识符只需一次replaceAll扫描即可完成所有词的匹配。替换时保持大小写getReplacementForPart会根据被匹配段的首字母大小写将推荐写法相应调整为upperFirst或lowerFirstrules/consistent-compound-words.js保证ViewPort→Viewport、viewPort→viewport这种大小写自适应的替换行为。编辑器建议修复先查冲突再重命名当命中变量时规则不会盲目建议重命名而是先做两件事作用域冲突检查通过getAvailableVariableName在同作用域内寻找无冲突的替换名并用scopeToNamesGeneratedByFixer记录本次报告已生成的名称避免多个建议互相冲突rules/consistent-compound-words.js 与 rules/consistent-compound-words.js安全重命名判断shouldRenameVariablerules/shared/identifier-checks.js会跳过被导出的标识符避免破坏export的外部契约与 JSX 标签名UserNameField /这类组件名重命名会引发解析错误。此外若变量被 Vue 模板引用reference.vueUsedInTemplate也只报错不给出重命名建议。满足条件时规则会生成一条带有fix的 suggestion实际执行重命名的是 rules/fix/rename-variable.js它通过getVariableIdentifiers收集该变量的全部标识符定义、引用、解构别名等逐一用replaceReferenceIdentifier替换为新名称。这也是为什么测试中能对function getUserName(userName) { return userName; }这类跨引用场景给出完整修复见 test/consistent-compound-words.js 的 invalid 用例。类作用域与 TypeScript 参数属性的特殊处理源码还处理了两个相对隐蔽的场景类名合成变量ESLint 的 scope 分析会为类名创建合成变量规则通过isClassVariable识别并合并外层类变量的引用避免重复报告rules/consistent-compound-words.js辅助函数见 rules/shared/identifier-checks.jsTypeScript 构造函数参数属性如constructor(private userName: string) {}这类标识符兼具“参数”与“属性”双重身份。规则中的isTSParameterPropertyName专门判断该场景当checkVariables关闭时仍可作为属性被检查而当两个开关都开启时测试显示它会被当作变量给出带修复的重命名建议输出constructor(private username: string) {}见 test/consistent-compound-words.js。使用建议与注意事项从默认配置开始该规则已包含在recommended与unopinionated预设中直接启用预设即可获得默认词表的检查单独启用可写作unicorn/consistent-compound-words: error。渐进式落地对存量代码库可先用allowList放行无法立即改动的历史名称如legacyUserName或通过replacements: {passWord: false}单独关闭某组争议词再逐步收敛。区分变量与属性默认checkProperties: false意味着属性名尤其是对象字面量键默认不受影响如果你的项目属性命名也需要统一再显式开启并留意它不会触碰字符串键、计算属性与 JSX 属性等外部 API 表面。导入名默认只查内部模块checkDefaultAndNamespaceImports与checkShorthandImports的internal默认值保证了外部依赖的命名不会被强行改写这通常是想要的行为只有对自研模块的导入名有强约束需求时再改为true。需要提醒的是该规则刻意不检查fileName、setUp、lookUp、newLine等常见歧义拼写详见“刻意不检查的内容”一节因此它解决的是“同一概念不同写法”的一致性问题而不是完整的命名风格规范——后者需要与仓库中其他命名类规则如 name-replacements配合使用。若在编辑器中看到“PreferusernameoveruserName.”或“Rename tousername.”的提示前者是规则报错信息后者是可点击执行的编辑器建议点击后规则会基于作用域分析自动完成全部引用的安全重命名。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考