【问题标题】:Typings for a Mediator Pattern in TypeScriptTypeScript 中中介者模式的类型
【发布时间】:2020-07-19 22:09:16
【问题描述】:

我正在尝试在 TypeScript 中创建一个 typed 中介模式。该模式本身可以正常工作,但我希望它完全输入而没有冗余(没有分别为命令注册和调度程序定义特定类型)。

这意味着每当我这样做时:

dispatchCommand({
type: "SAVE_EVIDENCE_EVALUATION",
command: {
 // This gets autocompleted with the right typing
}

这是我到目前为止所做的事情:

无类型中介代码

let commands = {};
    export const registerCommand = ({ type, handler }) => {
      commands[type] = handler;
    };

    export const dispatchCommand= async ({ type, command }) => {
      logTime(type);
      return commands[type](command);
    };

我会像这样注册命令:

registerCommand("CREATE_NEW_INSTITUTION_ACCOUNT", CreateNewInstitutionAccountCommandHandler);

我会解雇它,像这样:

const result = await dispatchCommand("CREATE_NEW_INSTITUTION_ACCOUNT", { 
  tenantId: 'my-id',
  employeeId: 'the-other-id'
});

我已经尝试了几个小时来了解如何创建共享类型,因此我可以安全地使用已经可用的类型注册命令。

注意:我总是可以做 2 种类型,但这会有点违背类型系统的目的,因为我总是忘记在几个地方添加它

这是目前的方法(TypeScript):

type MediatorDispatcherForCommands = (({
  type,
  handler,
  command,
}: {
  type: "SAVE_EVIDENCE_EVALUATION";
  handler?: typeof SaveEvidenceEvaluationCommandHandler;
  command?: SaveEvidenceEvaluationCommand;
}) => ReturnType<typeof SaveEvidenceEvaluationCommandHandler>) &
  (({
    type,
    handler,
    command,
  }: {
    type: "SEED_DATABASE_INDIVIDUAL";
    handler?: typeof SaveEvidenceEvaluationCommandHandler;
    command?: SeedDataForIndividualAccountCommand;
  }) => ReturnType<typeof SeedDataForIndividualAccountCommandHandler>);

我尝试了无数种方法。我试过把它分成不同的对象。我已经尝试过强制要求一个参数(我不知道它何时在参数中被解构......通过解构它允许我在提供type 键时自动完成)。

这适用于调度程序,但不适用于命令。

   export const dispatchCommand: MediatorDispatcherForCommands = async ({ type, command }) => {
      logTime(type);
      return commands[type](command);
    };

有什么想法吗?

【问题讨论】:

    标签: typescript typescript-typings mediator


    【解决方案1】:

    我最终放弃了一个通用的解决方案......这是我能得到的最接近的解决方案:

    我会在参数参数中进行联合操作。这将允许我在需要时自动完成。

    稍后,在调度程序中,我将创建一个返回类型,并明确传递它。

    往下看:

    这允许我在调度程序和注册器中自动完成它。

    export type MediatorCommands =
      | {
          type: "CREATE_ROLE";
          arg: CreatePermissionCommand | typeof createPermissionCommandHandler;
        }
      | {
          type: "CREATE_NEW_INSTITUTION_ACCOUNT";
          arg:
            | CreateNewInstitutionAccountCommand
            | typeof CreateNewInstitutionAccountCommandHandler;
        }
    

    然后是我的功能:

    // This is hacky... but it works!
    let commands: {
      [x: string]: Function;
    } = {};
    
    export function registerCommand({ type, arg }: MediatorCommands) {
      commands[type] = arg as Function;
    }
    
    export async function dispatchCommand<TResult>({
      type,
      arg,
    }: MediatorCommands) {
      logTime(type);
      return commands[type](arg) as Promise<TResult>;
    }
    

    然后,注册一个命令:

    registerCommand({
      type: "CREATE_ROLE",
      arg: createPermissionCommandHandler,
    });
    

    然后,你可以这样做:

    await dispatch<CreatedRoleRT>({
              type: "CREATE_ROLE",
              arg: {
                tenantId,
                employeeId,
              },
            });
    

    CreatedRoleRT 类型来自另一个单一文件(以减少依赖关系),该文件包含处理程序返回类型的所有引用。

    type CreatedRoleRT = ReturnType<typeof createPermissionCommandHandler>;
    

    这并不完美......但它有效?!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-14
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-21
      相关资源
      最近更新 更多