
eslint-plugin-unicorn 规则实战prefer-set-size —— 用Set#size替代Array#length【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇文章以 eslint-plugin-unicorn 项目中prefer-set-size规则的文档、源码实现与快照测试为依据系统讲解该规则的核心原理、自动修复行为与边界处理。读完你将掌握什么代码会被该规则报告、[...set].length与Array.from(set).length两种模式的修复逻辑、哪些特殊情况会被安全跳过以及如何通过 ESLint 的--fix一键完成替换。规则概览prefer-set-size是 eslint-plugin-unicornGitHub 推荐项目精选 / es / eslint-plugin-unicorn提供 300 条 ESLint 规则中一条专注于 JavaScriptSet用法的规则。其核心主张来自官方文档 docs/rules/prefer-set-size.mdSet#size是获取Set中元素数量的直接方式。为了读取.length而把Set转成数组是低效的也违背了使用 Set 的初衷。size属性是 O(1) 的且不需要任何转换。从规则元信息rules/prefer-set-size.js可以看到它的定位类型suggestion建议型可自动修复fixable: code支持 ESLint 的--fixCLI 选项推荐配置recommended✅与unopinionated☑️适用语言js/js报错信息Prefer using \Set#size instead of Array#length.消息 ID 为prefer-set-size典型反模式两种会被报告的写法根据规则源码中的getSetNode函数rules/prefer-set-size.js该规则只针对两种具体的 AST 形态1. 展开语法 length[...set].length// ❌ 触发规则 function isUnique(array) { return [...new Set(array)].length array.length; } // ✅ 正确写法 function isUnique(array) { return new Set(array).size array.length; }// ❌ 触发规则 const items new Set([1, 2, 3, 4, 5]); if ([...items].length 3) { // do something } // ✅ 正确写法 const items new Set([1, 2, 3, 4, 5]); if (items.size 3) { // do something }// ❌ 触发规则 const uniqueCount [...new Set(userIds)].length; // ✅ 正确写法 const uniqueCount new Set(userIds).size;2.Array.fromlengthArray.from(set).length// ❌ 触发规则 Array.from(new Set(array)).length; // ✅ 正确写法 new Set(array).size;检测条件非常严格Array.from必须恰好只有一个参数argumentsLength: 1且不允许可选调用/可选成员访问optionalCall: false、optionalMember: false。因此Array.from(new Set(array), mapFn).length、Array?.from(...).length、Array.from?.(...).length都不会被报告。触发条件与识别机制外层必须是成员表达式.length规则的create函数监听MemberExpression节点rules/prefer-set-size.js要求property严格为length不允许可选访问optional: false因此[...set]?.length会被跳过必须是字面属性访问因此[...set][length]、[...set][length]计算成员也都会被跳过。内部必须是真正的Set仅凭语法形态还不够规则通过isSet()工具rules/utils/is-set.js做类型判定。该工具基于createBuiltinTypeCheckersrules/utils/type-helpers.js实现将类型收敛为三种target确定是 Set、non-target确定不是、unknown无法确定。其识别能力包括字面构造new Set(...)直接判定为目标变量追踪const foo new Set([]); [...foo].length会沿作用域链追踪变量定义resolveIdentifierName确认foo是 SetTypeScript 类型标注对Setstring、ReadonlySetstring等类型注解同样识别ReadonlySet被注册为Set的别名排除反例new NotSet(...).length、[...Set(array)].length函数调用而非构造、let foo new Set([]); [...foo].length可重新赋值的变量、解构绑定的foo、重复var声明等均被判定为non-target或unknown而跳过。数组元素必须是单一的展开元素[...set].length形态还要求数组表达式elements.length 1且唯一元素是SpreadElement。因此[...new Set(array), foo].length、[foo, ...new Set(array)].length不会被误报。自动修复快照测试逐项验证的边界行为快照文件 test/snapshots/prefer-set-size.js.md 记录了 20 个 invalid 用例的完整「输入 → 报错 → 修复输出」对照来源是测试文件 test/prefer-set-size.js。以下按修复要点分类说明。基础替换.length→.size最简单的场景直接把属性名替换并删除多余的数组展开输入: [...new Set(array)].length 输出: new Set(array).size输入: Array.from(new Set(array)).length 输出: new Set(array).size变量场景保持赋值与引用结构当 Set 已绑定到变量时修复只替换读取处不动声明处输入: const foo new Set([]); console.log([...foo].length); 输出: const foo new Set([]); console.log(foo.size);输入: function getSize(set: Setstring) { return Array.from(set).length; } 输出: function getSize(set: Setstring) { return set.size; }多余括号修复后同样得到清理规则能识别并剥离[...(( new Set(array) ))]、(( [...new Set(array)] )).length、(( Array.from(new Set(array)) )).length等冗余括号层级输入: [...(( new Set(array) ))].length 输出: new Set(array).size输入: (( [...new Set(array)] )).length 输出: (( new Set(array) )).size注意最后一例最外层的括号属于数组表达式外层、与成员访问连写(( ... )).length修复后保留因为去掉会改变语义。注释保留数组内或new与Set之间的注释在修复中会被完整保留输入: [/* comment */...new Set(array)].length 输出: new Set(array).size 输入: [...new /* comment */ Set(array)].length 输出: new /* comment */ Set(array).size实现上createFix会对比array与set内部包含的注释数量sourceCode.getCommentsInsiderules/prefer-set-size.js若被删除的数组表达式内部注释多于set内部的注释则放弃自动修复只报错不修避免丢失注释。括号补全TypeScript 类型断言场景修复的核心动作是「把set文本替换为成员表达式的对象」。当set是 TypeScript 类型断言如set as Setstring时直接拼成set as Setstring.size会解析出错因此规则调用shouldAddParenthesesToMemberExpressionObjectrules/utils/should-add-parentheses-to-member-expression-object.js判断是否需要加括号输入: function getSize(set: unknown) { return [...(set as Setstring)].length; } 输出: function getSize(set: unknown) { return (set as Setstring).size; } 输入: function getSize(set: unknown) { return Array.from(set as Setstring).length; } 输出: function getSize(set: unknown) { return (set as Setstring).size; }该工具按节点类型分策略Identifier、CallExpression、TemplateLiteral等作为成员对象本就安全返回falseNewExpression仅在已有括号时安全其他类型含 TS 断言默认需要补括号。这条规则同样适用于no-unused-builtin-method-return、no-loop-iterable-mutation等复用isSet的其他规则。关键字空格修复在[...set].length场景中array被替换为new Set(...)后可能出现return new Set(array).size这种关键字return与新表达式紧贴的情况。因此createFix在数组表达式分支额外调用fixSpaceAroundKeywordrules/fix/fix-space-around-keywords.js检测替换范围前后的 token若前/后是纯小写关键字或of、await且与范围紧邻就插入一个空格。输入: function isUnique(array) { return[...new Set(array)].length array.length } 输出: function isUnique(array) { return new Set(array).size array.length }语句开头场景当数组表达式出现在语句开头前面有分号时修复同样正确衔接输入: foo ;[...new Set(array)].length 输出: foo ;new Set(array).size如何在自己的项目中使用该规则属于插件的一部分无需单独配置。在你的 ESLint 配置中启用unicorn/prefer-set-size即可{ plugins: [unicorn], rules: { unicorn/prefer-set-size: error } }由于规则fixable: code可以直接用 ESLint 的--fix自动修复npx eslint . --fix如果你使用插件提供的recommended或unopinionated预设配置该规则会自动启用。执行前建议先运行不带--fix的检查npx eslint .预览报告再决定是否一键修复。总结prefer-set-size规则针对 JS 开发中常见的「把 Set 转成数组数长度」反模式提供了完备的检测与安全自动修复它严格限定.length成员访问与单一展开元素/单参数Array.from两种形态通过isSet类型推理避免误报并在修复时妥善处理括号、注释、关键字空格与 TypeScript 类型断言。其 20 个快照测试用例test/snapshots/prefer-set-size.js.md、test/prefer-set-size.js完整覆盖了这些边界行为可以作为理解规则行为边界的权威参考也方便你在接入该规则前评估其影响范围。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考