
eslint-plugin-unicornno-useless-undefined规则详解消除冗余的undefined写法【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn导读undefined是 JavaScript 中变量、参数、返回语句等的默认值显式书写它通常不会改变任何语义只会让代码变得更啰嗦。no-useless-undefined是 eslint-plugin-unicorn 提供的一条建议型suggestion规则用于自动检测并修复这些冗余的undefined同时通过精确的边界判断避免误伤需要保留显式undefined的场景如 TypeScript 联合返回类型、测试断言、React/Vue 状态管理 API 等。读完本文你将掌握该规则的全部检查范围、两个可配置选项的含义、它与 ESLint 内置规则的冲突处理方式以及其底层实现原理。规则概览no-useless-undefined的核心思想来自 JavaScript 语言的一条基本事实undefined是新变量、参数、返回语句等的默认值因此显式指定它不会产生任何差异。该规则会把这类冗余写法标记为错误并提供自动修复。属性值规则名称unicorn/no-useless-undefined规则类型suggestion建议型自动修复支持--fixCLI 选项可修复fixable: code编辑器建议支持手动修复建议hasSuggestions: true推荐配置✅recommended、☑️unopinionated见 configs/flat-config-base.js 与规则源码 rules/no-useless-undefined.js 中的docs.recommended语言支持规则源码languages: [js/js]即主要针对 JavaScript/TypeScript.ts、.mts、.cts、.tsx文件在规则实现中判断一个节点是否为undefined使用的是 rules/ast/is-undefined.js 中的辅助函数仅当节点是Identifier类型且名称为undefined时才成立这保证了不会误判其他变量名。检查范围与修复示例该规则会在以下九类场景中报告冗余的undefined每类都对应一条明确的源码分支见 rules/no-useless-undefined.js 中的context.on(Identifier, ...)处理器。1. 变量声明初始值let/var声明中undefined作为初始值会被删除const声明不受影响因为const必须要有初始值源码中通过parent.parent.kind ! const显式排除// ❌ let foo undefined; // ✅ let foo;2. 解构默认值对象解构与数组解构中的undefined默认值同样会被删除// ❌ const {foo undefined} bar; // ✅ const {foo} bar;// ❌ const [foo undefined] []; // ✅ const [foo] [];3. 箭头函数体当箭头函数的函数体直接是undefined时会被替换为空块语句// ❌ const noop () undefined; // ✅ const noop () {};4. 函数返回语句// ❌ function foo() { return undefined; } // ✅ function foo() { return; }5. 生成器yield表达式// ❌ function* foo() { yield undefined; } // ✅ function* foo() { yield; }注意yield* undefined不会被报告因为yield*;本身不是合法语法源码中通过!parent.delegate排除测试用例见 test/no-useless-undefined.js。6. 函数参数默认值// ❌ function foo(bar undefined) { } // ✅ function foo(bar) { }7. 参数解构默认值// ❌ function foo({bar undefined}) { } // ✅ function foo({bar}) { }当删除的函数参数解构默认值带有 TypeScript 类型注解时修复器会自动插入?使其变为可选参数例如function foo({bar: string})会修复为function foo({bar?}: ...)的语义源码中fix分支通过left.typeAnnotation/isTypeScriptFile判断并插入?见 rules/no-useless-undefined.js。8. 函数调用末尾的实参仅 JavaScript// ❌ foo(undefined); // ✅ foo();修复逻辑位于context.on(CallExpression, ...)处理器中rules/no-useless-undefined.js只检查最后一个实参并且会复用 rules/fix/remove-argument.js 中的removeArgument修复器正确处理逗号、括号与尾随逗号如foo(bar, undefined,)→foo(bar,)。9. 带边界检查的索引访问编辑器建议// ❌ const foo index 0 ? array[index] : undefined; // ✅ const foo array[index];这类场景不会自动修复而是提供编辑器建议因为删除守卫条件会改变访问的执行时机array[index]从条件满足时才求值变成总是求值见规则文档原句与源码中problem.suggest的设置。三叉表达式索引访问的智能判定对于第 9 类场景规则的实现相当精巧。源码通过getIndexedAccess、getLowerBoundTestValidity、getUpperBoundTestValidity等函数rules/no-useless-undefined.js从语法层面推导索引访问是否等价于显式返回undefined下界判定形如index 0、index -1、index 5配合array[index - 5]的偏移量等比较只要确认访问索引与比较索引是同一个值通过isSame比较、偏移量是安全整数getStaticNumberValue就能判定访问在守卫条件成立时必定安全上界判定形如index array.length、index array.length - 1等与数组长度的比较通过isLengthOf/isLengthMinusOneOf辅助函数识别array.length及其减一形式安全性检查getIndexedAccess会拒绝带副作用的对象/属性访问hasSideEffect、可选链containsOptionalChain等不能安全提前求值的表达式。测试用例验证了多种等价写法均能被识别test/no-useless-undefined.jsconst foo index -1 ? array[index] : undefined; // → array[index] const foo index 0 ? undefined : array[index]; // → array[index] const foo index array.length - 1 ? array[index] : undefined; // → array[index] const foo index 5 ? array[index - 5] : undefined; // → array[index - 5]同时规则会保留被保留分支上的 TypeScript 类型断言如(array[index] as string)会修复为array[index] as string并处理换行时缺失分号的问题needsSemicolon判定见 rules/no-useless-undefined.js。如果三叉表达式内部存在任何注释规则会保留报告但不提供建议以避免误删注释。选项Options规则的 schema 定义在 rules/no-useless-undefined.js类型为object包含两个布尔选项默认值均通过defaultOptions: [{checkArguments: true, checkArrowFunctionBody: true}]声明。checkArguments类型boolean默认值true控制是否检查函数调用末尾的undefined实参。注意该选项仅对 JavaScript 文件生效TypeScript 文件永远不检查函数实参因为编译器会自行判断参数是否可以省略规则源码中通过isTypeScriptFile(context.physicalFilename)判断rules/utils/is-typescript-file.js 中定义了.ts/.mts/.cts/.tsx四种扩展名。// ❌ 默认配置下会被报告 /* eslint unicorn/no-useless-undefined: [error, {checkArguments: true}] */ foo(bar, baz, undefined); // ✅ foo(bar, baz);// ✅ 关闭该选项后保留 /* eslint unicorn/no-useless-undefined: [error, {checkArguments: false}] */ foo(bar, baz, undefined);checkArrowFunctionBody类型boolean默认值true控制是否检查箭头函数体直接为undefined的写法。当false时() undefined会被允许——文档说明这样做有时能让意图更明确。// ❌ /* eslint unicorn/no-useless-undefined: [error, {checkArrowFunctionBody: true}] */ const foo () undefined; // ✅ /* eslint unicorn/no-useless-undefined: [error, {checkArrowFunctionBody: true}] */ const foo () {};// ✅ /* eslint unicorn/no-useless-undefined: [error, {checkArrowFunctionBody: false}] */ const foo () undefined;配置示例ESLint 配置文件中{ rules: { unicorn/no-useless-undefined: [error, { checkArguments: false, checkArrowFunctionBody: false, }], }, }TypeScript 特殊处理函数实参完全不检查在.ts、.mts、.cts、.tsx文件中foo(undefined)这类调用不会被报告因为 TypeScript 中当参数类型包含undefined时如function testT extends object | undefined(argument: T)编译器可能要求显式传入undefined实参。测试用例明确覆盖了这一点test/no-useless-undefined.js。显式返回类型下的return undefined在 TypeScript 中当函数带有显式返回类型注解时return undefined仅在该返回类型是undefined或void时才被报告当返回类型是包含真实值类型的联合类型如number | undefined时显式undefined会被保留因为它可以表达文档意图并避免与 ESLint 内置的consistent-return规则产生冲突。// ❌ 返回类型是 undefined / void 时报告 function shouldBeFlagged(): undefined {return undefined;} function shouldBeFlagged(): void {return undefined;} // ✅ 联合返回类型保留 function getThing(): string | undefined { if (someCondition) { return hello world; } return undefined; // 保留 }源码通过isUndefinedOrVoidReturnType实现该判定只有TSUndefinedKeyword或TSVoidKeyword才允许修复rules/no-useless-undefined.js。测试还验证了以下边界情况test/no-useless-undefined.jsfunction foo(): number | void中的return undefined保留function foo(): any/unknown/never中的return undefined保留never既不是undefined也不是voidfunction foo(): undefined | number联合类型顺序不影响保留async function foo(): Promisevoid {return undefined;}保留——Promisevoid是类型引用而非void关键字报告时使用最内层函数的返回类型外层函数的返回类型不影响内层判断test/no-useless-undefined.js类的方法、getter、静态方法、私有方法、对象方法、导出函数等带显式返回类型的场景均会正确处理test/no-useless-undefined.js。注意上述返回类型相关行为仅在函数带有显式返回类型注解时生效没有返回类型注解时return undefined一律报告。被刻意忽略的调用Ignore 列表规则内置了一个shouldIgnore判定rules/no-useless-undefined.js当调用名命中以下集合时末尾的undefined实参不会被报告因为这些场景下undefined通常有实际语义用于断言值为 undefined或作为 API 的初始化值测试/断言函数is、equal、notEqual、strictEqual、notStrictEqual、propertyVal、notPropertyVal、not、include、property、toBe、toHaveBeenCalledWith、toContain、toContainEqual、toEqual、same、notSame、strictSame、strictNotSame数组与集合方法push、unshift、includes、add、has、deleteMapset如map.set(foo, undefined)React 相关createContext、useRefReact 19、以及以set开头的函数/^set[A-Z]/如setStateVue 相关refVue 响应式 APIref(undefined)是有意义的。测试用例完整覆盖了这些忽略场景test/no-useless-undefined.js并额外验证Function#bind()调用中除第一个this参数外的后续undefined实参会被忽略如foo.bind(bar, undefined)但foo.bind(undefined)会被报告test/no-useless-undefined.js可选链形式的setState?.(undefined)、props.setState?.(undefined)同样被忽略。与 ESLint 内置规则的冲突处理规则文档专门指出no-useless-undefined会删除return undefined而 ESLint 内置的array-callback-return与getter-return规则可能要求回调/ getter 必须显式返回一个值。若两者同时启用删除undefined后可能导致后两条规则报缺少返回值的错误。官方推荐为这两条 ESLint 规则设置allowImplicit: true以允许隐式返回undefined{ rules: { array-callback-return: [ error, { allowImplicit: true, }, ], getter-return: [ error, { allowImplicit: true, }, ], }, }源码级实现小结入口与注册规则在 rules/index.js 中注册可在unicorn/no-useless-undefined名下使用消息定义报告消息为Do not use useless \undefined.编辑器建议消息为Use the indexed access directly.rules/no-useless-undefined.js修复方式多数场景通过replaceNodeOrTokenAndSpacesBefore或removeRange直接删除节点及其前导空格保留注释实参场景复用 rules/fix/remove-argument.js 处理逗号与括号测试覆盖规则测试位于 test/no-useless-undefined.js共 872 行涵盖普通 JS、TypeScripttest.typescript、Vue 单文件组件parsers.vue以及修复快照test.snapshot四类测试场景。适用前提本文描述的行为以当前仓库源码为准。若你使用的是已发布的 npm 版本具体行为以该版本的文档与源码为准。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考