ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

eslint-plugin-unicorn no-anonymous-default-export:禁止匿名函数与类作为默认导出,让模块导出可搜索、可引用

eslint-plugin-unicorn no-anonymous-default-export:禁止匿名函数与类作为默认导出,让模块导出可搜索、可引用 eslint-plugin-unicorn no-anonymous-default-export禁止匿名函数与类作为默认导出让模块导出可搜索、可引用【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn导读no-anonymous-default-export是 eslint-plugin-unicorn 提供的一条 ESLint 规则用于拦截把匿名函数普通函数、异步函数、生成器函数、箭头函数或匿名类直接作为默认导出export default与 CommonJS 的module.exports/exports赋值的写法。阅读本文后你将掌握该规则的完整触发条件、命名建议的生成原理如何从文件名推导候选名、如何避免命名冲突、三种自动修复策略以及如何在自己的项目中启用它并规避误报。规则速览项目内容规则 IDunicorn/no-anonymous-default-export规则类型suggestion建议型修复方式手动修复通过编辑器建议触发hasSuggestions: true推荐配置✅recommended、☑️unopinionated适用语言js/js核心诉求命名默认导出保证模块默认导出的标识符在声明处与导入处保持一致提升代码库可搜索性以上信息分别来源于 规则文档 与 规则源码 的meta定义type: suggestion、recommended: unopinionated、hasSuggestions: true、languages: [js/js]。为什么要求命名默认导出默认导出default export是模块对外暴露的主入口在导入时可以随意改名import x from ./foo.js因此如果声明处使用匿名函数或匿名类代码库中就难以通过一致的标识符定位这个模块的核心导出。规则文档明确给出了设计意图Naming default exports improves codebase searchability by ensuring consistent identifier use for a modules default export, both where its declared and where its imported.即为默认导出命名能确保同一模块的默认导出在声明处和导入处使用一致的标识符从而显著提升代码库的可搜索性——无论是全局搜索、重构重命名还是阅读导入语句时快速理解模块职责。触发规则的模式与修正示例该规则覆盖两种模块体系ESM 的export default语法以及 CommonJS 的module.exports/exports赋值。以下全部示例来自 规则文档均完整可复现。ESMexport default匿名类// ❌ 匿名类 export default class {} // ✅ 具名类 export default class Foo {}ESMexport default匿名函数声明// ❌ 匿名函数声明 export default function () {} // ✅ 具名函数声明 export default function foo() {}ESMexport default箭头函数箭头函数在语法层面没有命名形态因此规则要求先赋给具名const再导出该变量// ❌ 匿名箭头函数 export default () {}; // ✅ 先命名再导出 const foo () {}; export default foo;CommonJSmodule.exports匿名类// ❌ module.exports class {}; // ✅ module.exports class Foo {};CommonJSmodule.exports匿名函数// ❌ module.exports function () {}; // ✅ module.exports function foo() {};CommonJSmodule.exports箭头函数// ❌ module.exports () {}; // ✅ const foo () {}; module.exports foo;规则如何判定匿名在 规则源码 中判定逻辑由isAnonymousClassOrFunction函数实现const isAnonymousClassOrFunction node ( [ FunctionDeclaration, FunctionExpression, ClassDeclaration, ClassExpression, ].includes(node.type) !node.id ) || node.type ArrowFunctionExpression;由此可以看出判定范围四类可命名的节点FunctionDeclaration、FunctionExpression、ClassDeclaration、ClassExpression只要没有id标识符即视为匿名ArrowFunctionExpression箭头函数天然不具备id一律视为匿名。由于判定基于 AST 节点类型而非文本形态async function、function*、async function*等变体同样会被捕获——这一点在 测试用例 中得到了完整验证如export default function * () {}、export default async function () {}、export default async () {}等均为无效用例。两种触发入口规则通过两个事件入口监听对应两种模块体系ExportDefaultDeclaration源码 L164-L170任何匿名类/函数直接作为export default的声明体时触发AssignmentExpression源码 L172-L196当赋值表达式的左侧满足以下条件之一时触发module.exports成员表达式且computed: false、optional: false裸标识符exportsnode.left.name exports且该赋值必须位于ExpressionStatement顶层node.parent.type ExpressionStatement node.parent.expression node即语句级别的直接赋值。编辑器自动建议如何从文件名派生候选名该规则不提供自动修复autofix但通过 ESLint 的 suggestions 机制提供手动修复建议开发者可在编辑器中一键应用。建议名称的生成逻辑位于源码getSuggestionNameL35-L51核心流程如下解析文件名path.basename(filename).split(., 1)取文件名主名去掉扩展名如foo-bar.test.js取foo-bar转换为小驼峰通过camelCase转换如foo-bar→fooBar校验标识符合法性调用isIdentifierName校验若文件名包含非法字符如foobar、foo*.js、[foo].js等见 is-identifier-name.js则不给出建议类名首字母大写当节点是ClassDeclaration或ClassExpression时用upperFirst将候选名转为大写开头foo→Foo去重避让调用getAvailableVariableName确保候选名不与现有代码冲突。命名冲突避让细节get-available-variable-name.js 是 unicorn 的通用命名工具它保证生成的名称不在给定作用域链的任何作用域中被定义过不会遮蔽已有变量不是 JavaScript 保留字或 TypeScript 保留字如class、interface、module、require等不是严格模式下的arguments不会与未解析的全局引用unresolved reference撞名——例如作用域内已经引用了未声明的foo则避免使用foo。若名称已占用则通过追加_后缀如foo_、foo__迭代直到唯一。测试用例中let Foo, Foo_, foo, foo_前置声明的场景正是为了验证这种避让行为见 测试 L89-L94。虚拟文件名的特殊处理isVirtualFilename见 is-virtual-filename.js用于识别 ESLint 的占位文件名inputstdin 输入与textLinter#verify未指定文件名。当文件名为这些占位符时规则不提供命名建议因为无法从文件名推导有意义的名字但仍会报告错误。三种修复策略的实现原理建议修复逻辑位于源码addNameL53-L115针对不同节点类型采用不同策略类ClassDeclaration/ClassExpression定位class关键字 token在其后插入name。实现时会先检查节点上的装饰器decorators若有装饰器则取装饰器之后的class关键字避免把名字插到装饰器前面函数FunctionDeclaration/FunctionExpression定位第一个左括号 token在其前插入name并处理空格细节若括号前已有空格则不再追加保证function name ()格式整洁箭头函数ArrowFunctionExpression由于箭头函数无法直接命名修复器将整条语句重构为两步把export default () {}改写为const foo () {}; export default foo;分号自动补全并通过文本切片保留原有注释与空白这也正是文档示例中 ✅ 写法的来源。错误消息与定位该规则定义了两条消息源码 L15-L20错误消息The {{description}} should be named.其中description会根据节点类型填充为class、function、arrow function等建议消息Name it as {{name}}.从 测试快照 可以看到实际的定位效果——错误会精准指向函数/类的头部位置 1 | export default function () {} | ^^^^^^^^^ The function should be named. 1 | export default class {} | ^^^^^ The class should be named.定位信息由getFunctionHeadLocation来自eslint-community/eslint-utils与getClassHeadLocationunicorn 内部工具提供。如何启用该规则该规则默认在recommended与unopinionated两套配置中启用见 规则文档使用这两套配置时无需额外声明。若需要单独启用可在 ESLint 配置中显式声明{ rules: { unicorn/no-anonymous-default-export: error } }采用 ESLint 新版 flat config 时import unicorn from eslint-plugin-unicorn; export default [ { plugins: {unicorn}, rules: { unicorn/no-anonymous-default-export: error, }, }, ];规则的导出注册见 rules/index.jsexport {default as no-anonymous-default-export} from ./no-anonymous-default-export.js;。不触发规则的合法场景以下写法不会触发该规则均来自 测试用例 的 valid 列表// 具名函数与具名类 export default function named() {} export default class named {} // 非函数/类的默认导出 export default []; export default {}; export default 1; export default false; export default 0n; // 非模块导出的匿名赋值左侧不是 module.exports / exports notExports class {}; notModule.exports class {}; module.notExports class {}; // 属性级导出右侧仍是匿名类但导出目标是属性而非整个默认导出 module.exports.foo class {}; // 嵌套赋值不是语句级别的直接赋值 foo module.exports class {};这些用例揭示了规则的边界设计它只关心整个默认导出值是否为匿名函数/类module.exports.foo ...这类子属性赋值、以及非语句级赋值都不在管辖范围内。测试与快照验证该规则的测试覆盖非常细致test/no-anonymous-default-export.js 中包含了多种语法变体普通/异步/生成器/异步生成器函数、箭头函数、带括号与注释的写法如export default (( () {} ))、跨行注释module // comment .exports () {}文件名边界foo.js、foo-bar.js、foo_bar.js、foobar.js、foo*.js、[foo].js、class.js、foo.helper.js、foo.test.js、.foo.js等验证候选名推导与合法性校验命名冲突预先声明Foo, Foo_, foo, foo_或Exports, Exports_, exports, exports_验证建议名称的避让与_后缀追加装饰器场景测试文件末尾还包含对带装饰器的类的验证。快照报告存放在 test/snapshots/no-anonymous-default-export.js.md逐条记录了每个无效用例的输入与错误输出可作为理解规则行为的权威参考。小结no-anonymous-default-export以命名默认导出这一单一诉求切入覆盖 ESM 与 CommonJS 两套模块体系并通过基于文件名的命名建议、作用域避让和三种差异化修复策略把为匿名导出取名从纯粹的规范约束变成了编辑器里一键可用的实操能力。对于希望提升代码库可搜索性、统一模块导出风格的项目这是一条低配置成本、高收益的规则。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表