尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

使用 Rome 的 useLiteralEnumMembers 规则:强制 TypeScript 枚举成员初始化为字面量

使用 Rome 的 useLiteralEnumMembers 规则:强制 TypeScript 枚举成员初始化为字面量 使用 Rome 的 useLiteralEnumMembers 规则强制 TypeScript 枚举成员初始化为字面量【免费下载链接】toolsUnified developer tools for JavaScript, TypeScript, and the web项目地址: https://gitcode.com/gh_mirrors/to/toolsuseLiteralEnumMembers 是 Rome现 Biome 前身在 v12.1.0 引入的一条 nursery 组推荐 lint 规则用于要求 TypeScript 枚举的所有成员都必须用常量表达式初始化。本指南将以该规则为核心讲解它的判定语义、合法与非法写法、源码级判定原理以及如何在rome.json中启用、关闭或调整严重级别帮助你写出可预测、易维护的枚举定义。规则概述为什么枚举成员应当使用字面量TypeScript 的enum语法非常灵活成员除了可以用数字或字符串字面量初始化外还允许被任意表达式赋值。但从工程实践看使用计算型computed枚举成员往往容易出错且难以理解——读者无法一眼看出枚举的实际取值重构时也容易引入隐藏的语义变化。useLiteralEnumMembers规则的定位正是收紧这一自由度它要求枚举成员的初始化值必须是常量表达式constant expression即数字或字符串字面量由字面量通过数值运算、位运算组合出的表达式用于支持经典的 enum flags 写法引用当前枚举中此前已声明的成员。该规则移植自 typescript-eslint 的 prefer-literal-enum-member 规则见规则文档中的 Source 声明与社区 lint 生态保持一致的判定口径。在仓库中该规则声明于 crates/rome_js_analyze/src/analyzers/nursery/use_literal_enum_members.rs归属于nursery规则组并在declare_rule!宏中标记为recommended: true即默认启用、默认按 error 级别报出其诊断类别为lint/nursery/useLiteralEnumMembers见 crates/rome_diagnostics_categories/src/categories.rs。非法示例Invalid当枚举成员使用计算型表达式初始化时规则会报错。以下是最基础的非法示例来自规则文档const x 2; enum Computed { A, B x, }B x引用了枚举外部的一个变量无法在编译期确定为常量因此规则会在x处产生如下诊断nursery/useLiteralEnumMembers.js:4:9 lint/nursery/useLiteralEnumMembers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ✖ The enum member should be initialized with a literal value such as a number or a string. 2 │ enum Computed { 3 │ A, 4 │ B x, │ ^ 5 │ } 6 │诊断消息固定为 The enum member should be initialized with a literal value such as a number or a string.报错范围精确指向初始化表达式本身实现中对initializer.range()报错。除了外部变量引用仓库的官方测试夹具 crates/rome_js_analyze/tests/specs/nursery/useLiteralEnumMembers/invalid.ts 还覆盖了更多被判定为非法的场景// 非字面量的字面量对象、数组、布尔、BigInt enum InvalidLiterals { A {}, B [], C true, D 1n, } // 带插值非常量的模板字符串 enum InvalidTemplateLiteral { A foo ${0}, } // 构造函数调用 enum InvalidConstructor { A new Set(), } // 不允许的一元/其它运算符 enum InvalidExpression { A delete 2, B -a, C void 2, D !0, } // 引用外部变量即便类型是字符串 const variable Test; enum InvalidVariable { A TestStr, V variable, } // 引用其它枚举的成员 enum Valid { A } enum InvalidEnumMember { A Valid.A, } // 位运算操作数本身不是常量引用外部变量 x const x 1; enum Foo { A x 0, B x 0, C x 0, D x | 0, E x 0, F x ^ 0, G ~x, } // 引用非法裸名引用、引用自身/后续成员、跨枚举引用 enum InvalidRef { A A, B InvalidRef.B, C InvalidRef[C], D E, E InvalidRef.F, F InvalidRef[G], G }注意最后几个用例体现了只能引用当前枚举中之前声明的成员这一细节A A引用自身、B InvalidRef.B引用自身、D E引用声明在后的成员全部会被拒绝对应的快照断言记录在 crates/rome_js_analyze/tests/specs/nursery/useLiteralEnumMembers/invalid.ts.snap 中每一个^标记都对应一条独立诊断。合法示例Valid以下写法均符合规则要求完整继承自规则文档// 1. 无初始化器由 TypeScript 顺序分配整数字面量 enum Direction { Left, Right, }// 2. 数字字面量含负数 enum Order { Less -1, Equal 0, Greater 1, }// 3. 字符串字面量 enum State { Open Open, Close Close, }// 4. 位运算组合enum flags 经典写法 enum FileAccess { None 0, Read 1, Write 1 1, All Read | Write }其中第 4 个示例正是规则为支持enum flags而特意放开的场景1 1是字面量参与的位移运算Read | Write是引用之前成员参与的按位或运算两者均被允许。仓库的合法用例夹具 crates/rome_js_analyze/tests/specs/nursery/useLiteralEnumMembers/valid.ts 进一步展示了边界情况enum ValidString { A test, B div ided, // 字符串拼接 C test2, // 无插值的模板字符串 D di ided2, AA A ValidString.A, // 引用之前成员参与拼接 } enum ValidNumber { A, B 42, C -42, // 一元负号 D 42, // 一元正号 E 2 2, // 算术运算 F A ValidNumber.B, // 引用之前成员 } enum ValidQuotedKey { A, // 引号键名成员 B 1, [C], } enum ValidFlags { A 1 0, B 1 0, C 1 0, D 1 | 0, E 1 0, F 1 ^ 0, G ~1, // 按位取反 } enum FileAccess { None 0, Read 1, Write 1 1, All (1 | (1 1)), // 括号包裹的常量表达式 } enum FileAccessWithRef { None 0, Read 1, Write FileAccessWithRef[Read] 1, // 计算成员访问形式 All Read | FileAccessWithRef.Write, } enum ValidRef { A, B, C A | B, // 裸名引用之前成员 }可以看到规则对引用的容忍度比直觉更宽既支持裸标识符引用A | B也支持EnumName.Member静态成员访问和EnumName[Member]计算成员访问但前提是被引用的成员必须已在当前枚举中先于当前成员声明。源码级判定原理规则实现的核心逻辑在 crates/rome_js_analyze/src/analyzers/nursery/use_literal_enum_members.rs 中可以拆解为两层1. 遍历枚举成员run方法L79-L111规则查询类型为AstTsEnumDeclaration即每次分析一个枚举声明先取出枚举名enum_declaration.id()用于后续校验限定名引用用一个FxHashSet记录已经遍历过的成员名保证只允许引用之前的成员逐个遍历enum_declaration.members()若成员没有初始化器直接放行对应顺序分配整数字面量的语义如enum Direction { Left, Right }若成员有初始化器将其表达式交给is_constant_enum_expression判定不通过则把该表达式的TextRange加入诊断信号列表最后把当前成员名记入集合供后续成员引用。2. 常量表达式校验is_constant_enum_expressionL131-L199校验采用一个显式栈对表达式树做深度优先遍历逐节点匹配允许的表达式类型表达式类型判定规则对应示例字面量表达式仅接受数字字面量JsNumberLiteralExpression和字符串字面量JsStringLiteralExpression对象、数组、布尔、BigInt 一律拒绝{}、[]、true、1n均非法模板字符串必须调用is_constant()判定为常量即无插值或插值部分为常量foo ${0}非法test2合法一元表达式仅接受BitwiseNot~、Minus-、Plus三种运算符其余如delete、void、!拒绝-42、42、~1合法二元表达式必须是二元运算is_binary_operation或数值运算is_numeric_operation即算术与位运算类随后压栈继续校验左右操作数2 2、1 1、Read \| Write合法标识符引用名字必须命中当前枚举的已声明成员名集合A \| B合法A A、D E非法静态/计算成员访问调用is_enum_member_reference对象必须是当前枚举名object.has_name(enum_name)且成员名命中已声明集合FileAccessWithRef.Write、FileAccessWithRef[Read]合法Valid.A跨枚举非法其它表达式一律拒绝如new Set()构造调用new Set()非法is_enum_member_referenceL203-L215负责成员访问的最终校验先剥离括号取得对象表达式确认其是引用标识符且名字与当前枚举名一致再确认expr.member_name()命中已声明成员集合。整条路径返回Optionbool任何一步解析失败都会通过unwrap_or_default()收敛为false即判为非法保证规则在语法异常时也不会误放行。值得注意的边界是位运算本身不豁免操作数必须为常量。例如x 0操作数是外部变量x虽然看起来是位运算但因为x不是字面量或已声明枚举成员仍会被判为非法——测试夹具invalid.ts中的enum Foo正是为了锁定这一语义。配置与使用默认行为由于declare_rule!中声明了recommended: true见 use_literal_enum_members.rs该规则随nursery组默认启用诊断以 error 严重级别输出。在 rome.json 中显式配置规则配置通过linter.rules.nursery下的键useLiteralEnumMembers控制对应的配置字段定义在 crates/rome_service/src/configuration/linter/rules.rs 中。显式设为 error{ linter: { enabled: true, rules: { nursery: { useLiteralEnumMembers: error } } } }调整为 warn适合重构期避免阻断 CI{ linter: { enabled: true, rules: { nursery: { useLiteralEnumMembers: warn } } } }完全关闭{ linter: { enabled: true, rules: { nursery: { useLiteralEnumMembers: off } } } }level字段的可选值为off、warn、error。规则选项该规则不接收任何额外选项——实现中type Options ()明确声明了无选项use_literal_enum_members.rs因此配置时只需给出严重级别字符串无需也不应传入options对象。逐行忽略如需在某一行临时豁免该规则可在报错行上方添加 suppression 注释格式为// rome-ignore lint/nursery/useLiteralEnumMembers: explanation enum Foo { A someComputedValue, }更详细的规则禁用、选项配置与忽略语法参见 Linter 使用指南 与 Rule options。小结useLiteralEnumMembers通过把枚举成员限定为字面量、字面量参与的数值/位运算表达式、以及当前枚举内部的前向成员引用在不牺牲 enum flags 等合法常量组合能力的前提下消除了计算型枚举成员带来的可读性与可维护性隐患。配合仓库自带的 invalid.ts / valid.ts 测试夹具你可以在改动枚举时快速验证自己的写法是否符合该规则从而写出自解释、可预期的 TypeScript 枚举。【免费下载链接】toolsUnified developer tools for JavaScript, TypeScript, and the web项目地址: https://gitcode.com/gh_mirrors/to/tools创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表