- 前端
- 状态管理
【免费下载链接】platform
Reactive State for Angular
导读
prefer-action-creator是 NgRx ESLint 插件中针对store模块提供的一条代码风格(suggestion)规则,核心主张是:使用createAction生成的 Action Creator,优于手写的Action类。本文将以仓库中的官方规则文档为主体,结合规则源码(prefer-action-creator.ts)、配套测试(prefer-action-creator.spec.ts)以及内置配置(store.ts)深入讲解该规则的作用范围、触发条件、违规/合规示例与启用方式,帮助你理解并落实 NgRx 推荐的 Action 书写范式。
规则概览
该规则的元数据定义在源码的meta字段中,与官方文档页首的生成内容一一对应:
| 属性 | 值 | 说明 |
|---|---|---|
| Type | suggestion | 属于代码风格建议类规则,不代表程序运行错误 |
| Fixable | No | 不可自动修复,需要开发者手动改写代码 |
| Suggestion | No | 不提供编辑器内的自动修复建议(suggestion fix) |
| Requires type checking | No | 基于纯语法分析即可工作,无需类型信息,运行开销低 |
| Configurable | No | 不接受任何配置选项,schema为空数组 |
| ngrxModule | store | 归入 NgRx 的 store 模块规则集 |
上述信息在源码 prefer-action-creator.ts 中有直接体现:type: 'suggestion'、schema: []、docs.ngrxModule: 'store'。由于不依赖类型检查(requiresTypeChecking为false),它可以在常规(非 type-checked)ESLint 配置中直接运行。
Rule Details:规则判定逻辑
规则的命名与报告信息非常直白:
- 规则名:
prefer-action-creator(对应 ESLint 配置键@ngrx/prefer-action-creator) - 报告消息(messageId 为
preferActionCreator):"UsingAction classis forbidden. Useaction creatorinstead."
违规(incorrect)代码示例
当类声明同时满足以下两个特征时,即触发本规则:
- 类实现了
Action接口(写法可以是implements Action,也可以是带命名空间的implements ngrx.Action); - 类内部定义了名为
type的属性(无论是否加readonly,也无论type的值是字符串字面量还是来自常量的引用)。
// 违规:实现 Action 接口且带有 type 属性 class Test implements Action { type = '[Customer Page] Load Customer'; } class Test implements ngrx.Action { readonly type = ActionTypes.success; constructor(readonly payload: Payload) {} }合规(correct)代码示例
以下三种写法都不会触发规则:
// 合规:使用 createAction 创建 Action Creator export const loadUser = createAction('[User Page] Load User'); // 合规:类虽然定义了 type 属性,但没有实现 Action 接口 class Test { type = '[Customer Page] Load Customer'; } // 合规:类实现了 Action 接口,但属性名是 member 而非 type class Test implements Action { member = '[Customer Page] Load Customer'; }源码层的触发条件
规则的实现非常精炼,完整逻辑只有一行基于 AST 的选择器表达式,见 prefer-action-creator.ts:
`ClassDeclaration:has( TSClassImplements:matches( [expression.name='Action'], [expression.property.name='Action'] ) ):has(PropertyDefinition[key.name='type'])`拆解这段选择器可以精确还原规则的判定范围:
ClassDeclaration:仅针对类声明;TSClassImplements:要求类实现了某个接口;[expression.name='Action']与[expression.property.name='Action']:分别匹配implements Action与implements ngrx.Action两种书写形式,其中后者的接口名位于命名空间的property位置;:has(PropertyDefinition[key.name='type']):类体内必须包含名为type的类属性。
一旦命中,规则直接在类声明节点上报告错误。从选择器可推断,判定是纯结构性的:不关心type的值来源(字面量或常量引用)、不关心是否readonly,也不进行类型检查。
规则背后的设计动机:为何优先使用 Action Creator
该规则倡导的Action Creator源自createAction工厂函数,定义于 modules/store/src/action_creator.ts。createAction接受描述动作的字符串type,返回一个可调用的 Creator 函数,调用后即产生符合Action接口的对象。
使用 Action Creator 相比 Action 类的主要优势(在 action_creator.ts 的@usageNotes中均有对应用法演示):
- 样板代码更少:无需手写
class、constructor、字段初始化,一行createAction即可声明动作; - 类型更安全:配合
props<T>()或emptyProps()可将载荷(payload)的类型直接编码进 Creator,dispatch 时自动获得完整的类型推断; - 统一的消费方式:Creator 可直接传入
store.dispatch、reducer 的on(...)以及 effect 的ofType(...)中,与 NgRx 其余 API 无缝衔接,避免了类式 Action 在 reducer/effect 中反复做类型断言的麻烦; - 可扩展元数据:
createAction还支持传入自定义 Creator 函数以附加额外元数据(见 action_creator.ts 的重载签名)。
官方文档与源码注释(见 action_creator.ts)均明确指出:Action Creator 就是为降低类式 Action 的"显式性"(explicitness)而设计的更优形态。
如何启用该规则
通过内置配置一键启用
prefer-action-creator已被纳入插件的两套内置配置,默认以'error'级别开启:
- store 配置(configs/store.ts):启用所有 store 模块相关规则;
- all 配置(configs/all.ts):启用插件全部规则。
即安装插件后,直接在 ESLint 的 flat config 中引入@ngrx/store或@ngrx/all配置即可生效,无需额外配置该规则。
单独配置
该规则不可配置(Configurable: No),因此没有参数可调,只能控制开关与严重级别。需要单独启用时,可在 ESLint 配置中声明:
export default [ // ... 其他配置 { name: 'ngrx/prefer-action-creator', rules: { '@ngrx/prefer-action-creator': 'error', // 也可设为 'warn',以告警而非报错的形式提示 }, }, ];测试用例佐证
规则仓库内置的测试文件 prefer-action-creator.spec.ts 使用@typescript-eslint/rule-tester驱动,其中:
- **有效用例(valid)**共 4 条:
createAction调用、无Action接口的普通类、实现了Action但属性名为member的类、仅构造器带参数而type为readonly常量引用但不实现Action接口的类; - **无效用例(invalid)**共 2 条:
implements Action与implements ngrx.Action两种写法,均通过fromFixture标记出完整的违规区间,并断言报告的消息 ID 为preferActionCreator。
这些用例与官方文档中的违规/合规示例完全一致,构成了规则行为的可执行证据:只要"实现Action接口 + 存在type属性"同时成立,无论type是字符串字面量还是常量引用、是否带readonly,都会被报告。
与相邻规则的协同
prefer-action-creator并非孤立存在,它与其他两条规则共同构成了 NgRx 对 Action 书写方式的完整约束(三者在 configs/store.ts 中相邻出现):
prefer-action-creator-in-dispatch(prefer-action-creator-in-dispatch.ts):进一步约束store.dispatch(...)的调用处,禁止直接传入new出的旧式 Action 对象或普通对象字面量,必须使用 Action Creator;prefer-action-creator-in-of-type(effects 模块,见 configs/effects.ts):约束 effect 中ofType(...)的用法,同样要求传入 Action Creator。
三者合起来意味着:从声明(本条规则)到dispatch 调用再到effect 的 ofType 监听,NgRx 推荐在 Action 的整个生命周期内都使用createAction创建的函数形式,彻底淘汰类式 Action 的写法。这也与createAction设计为可同时作为"类型描述"与"值"使用的特性(见 action_creator.ts 中 reducer 的on与 effect 的ofType用法)相吻合。
小结
prefer-action-creator是一条实现极简、语义明确、开箱即用的代码风格规则:凡是"实现了Action接口且定义了type属性的类"都会被标记并提示改用createAction。它不需要类型检查、不支持自动修复、也不接受配置,配合@ngrx/store内置配置即可立刻生效。对于正在推行 NgRx 推荐 Action 写法的团队,将它与prefer-action-creator-in-dispatch、prefer-action-creator-in-of-type搭配使用,可以在声明、dispatch、effect 三个层面全面统一为 Action Creator 范式。
- 前端
- 状态管理
【免费下载链接】platform
Reactive State for Angular
相关推荐
ESLint prefer-spread 规则详解:用展开运算符替代 `Function.prototype.apply()`
ESLint prefer spread 规则详解:用展开运算符替代 Function.prototype.apply 导读 prefer spread 是 E
开发工具Lint静态分析代码质量eslint-plugin-unicorn 规则详解:prefer-dom-node-text-content —— 用 `.textContent` 替代 `.innerText`
eslint plugin unicorn 规则详解:prefer dom node text content —— 用 .textContent 替代 .in
Lint代码质量eslint-plugin-unicorn prefer-regexp-escape 规则详解:用 `RegExp.escape()` 替代手写正则转义
eslint plugin unicorn prefer regexp escape 规则详解:用 RegExp.escape 替代手写正则转义 导读 pref
Lint代码质量
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考