代码之家  ›  专栏  ›  技术社区  ›  Jose A

TypeScript中中介模式的键入

  •  0
  • Jose A  · 技术社区  · 4 年前

    我想创造一个 打字 TypeScript中的中介模式。该模式本身可以正常工作,但我希望它完全类型化,而没有冗余(不单独为命令注册和分派器定义特定类型)。

    这意味着每当我这样做:

    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个类型,但这会有点挫败类型系统的目的,因为我总是忘记在几个地方添加它

    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);
        };
    

    有什么想法吗?

    0 回复  |  直到 4 年前
        1
  •  -1
  •   Jose A    4 年前

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

    我会在参数中做一个并集运算。这将允许我在需要时自动完成。

    稍后,在dispatcher中,我将创建一个返回类型,并显式地传递它。

    见下表:

    这允许我在dispatcher和registrar中自动完成它。

    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>;
    

    这并不完美。。。但它是有效的!