You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动将项目中800余个Ngrx旧Action改写为Action Group?

将Ngrx旧版独立Action批量转换为Action Group的方法

旧版Action示例

export const GetAction = createAction(
  '[BOOK] GET',

  props<{
    filter: BookFilterModel,
  }>(),
);

export const GetFailAction = createAction(
  '[BOOK] GET_FAIL',
);

export const GetSuccessAction = createAction(
  '[BOOK] GET_SUCCESS',

  props<{
    book: BookModel,
  }>(),
);

可行的批量转换方法

1. Ngrx官方迁移工具

Ngrx内置了schematics迁移工具,可自动将旧版独立Action转换为Action Group。确保项目已安装@ngrx/schematics,终端运行以下命令:

ng generate @ngrx/schematics:migrate action-groups

该命令会扫描项目中所有createAction定义的独立Action,自动按Action类型前缀(如[BOOK])分组,重构为对应的Action Group类。

2. 自定义TypeScript AST脚本

如果官方工具无法覆盖特殊场景,可使用ts-morph这类AST处理工具编写自定义转换脚本,精准控制转换逻辑:

  • 遍历项目中所有Action定义文件
  • 识别每个createAction调用,提取Action类型字符串、参数props信息
  • 按前缀分组(如[BOOK]),生成对应的Action Group类
  • 替换原有独立Action定义

示例简化逻辑代码:

import { Project, SyntaxKind } from 'ts-morph';

const project = new Project();
project.addSourceFilesAtPaths('src/**/*.actions.ts');

project.getSourceFiles().forEach(sourceFile => {
  // 提取所有createAction定义的Action节点
  const actionNodes = sourceFile.getVariableDeclarations().filter(decl => 
    decl.getInitializer()?.getKind() === SyntaxKind.CallExpression &&
    (decl.getInitializer() as any).getExpression().getText() === 'createAction'
  );

  // 按前缀分组Action
  const actionGroups: Record<string, any[]> = {};
  actionNodes.forEach(node => {
    const actionTypeArg = (node.getInitializer() as any).getArguments()[0].getText();
    const prefix = actionTypeArg.match(/^\[(\w+)\]/)[1];
    if (!actionGroups[prefix]) actionGroups[prefix] = [];
    actionGroups[prefix].push({
      name: node.getName().replace('Action', ''),
      type: actionTypeArg,
      props: (node.getInitializer() as any).getArguments()[1]?.getText()
    });
  });

  // 生成Action Group类
  Object.entries(actionGroups).forEach(([prefix, actions]) => {
    const className = `${prefix}Actions`;
    const classDeclaration = sourceFile.addClass({
      name: className,
      isExported: true,
    });
    actions.forEach(action => {
      classDeclaration.addMethod({
        name: action.name.toLowerCase(),
        isStatic: true,
        returnType: `Action`,
        bodyText: `return createAction(${action.type}${action.props ? `, ${action.props}` : ''});`
      });
    });
    // 删除原有独立Action定义
    actionNodes.forEach(node => node.remove());
  });

  sourceFile.save();
});

3. IDE正则批量替换

对于命名规则统一的Action(如XxxAction、XxxFailAction、XxxSuccessAction),可借助IDE的正则替换功能批量处理:

  • 匹配同一组的所有Action定义
  • 替换为Action Group类的成员方法

示例正则(以IntelliJ系IDE为例):
查找模式:

export const (\w+)Action = createAction\(
  '\[BOOK\] (\w+)',
  (props<\{[^}]+\}>)?\);

替换模式:

static $1() {
  return createAction('[BOOK] $2'$3);
}

替换后手动补充Action Group的类定义,将方法包裹其中。


内容的提问来源于stack exchange,提问作者Dmitriy Ivanko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:47:09