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

如何为TypeScript调度函数实现返回类型自动推断?

实现带自动类型推断的Dispatch函数

要让TypeScript根据传入的type自动推断args类型和返回值类型,核心是利用泛型+映射类型,基于commandsOrQueries的具体类型自动推导关联关系,而非手动维护联合类型。

解决方案步骤

1. 锁定命令/查询对象的类型

给commandsOrQueries添加as const,让TypeScript保留其键和值的具体类型(避免被宽泛的Record<string, Function>覆盖):

const commandsOrQueries = {
  CREATE_USER_WITH_PASSWORD: CreateUserCommandHandler,
  GET_USERS: GetUsersQueryHandler,
  GET_USER_PROFILE: GetUserProfileQueryHandler
} as const;

2. 定义辅助类型

通过TypeScript内置工具类型(Parameters/ReturnType)自动提取类型信息:

// 提取所有命令/查询的类型键
type CommandOrQueryType = keyof typeof commandsOrQueries;

// 根据类型键获取对应的处理函数类型
type Handler<T extends CommandOrQueryType> = typeof commandsOrQueries[T];

// 获取处理函数的参数类型
type HandlerArgs<T extends CommandOrQueryType> = Parameters<Handler<T>>[0];

// 获取处理函数的返回类型
type HandlerReturn<T extends CommandOrQueryType> = ReturnType<Handler<T>>;

3. 定义Dispatch函数的参数类型

用泛型关联type和arg的类型,确保两者严格对应:

type DispatchParams<T extends CommandOrQueryType> = {
  type: T;
  arg: HandlerArgs<T>;
};

4. 实现Dispatch函数

通过泛型让TypeScript自动推断返回值类型:

export async function dispatch<T extends CommandOrQueryType>({ type, arg }: DispatchParams<T>): Promise<HandlerReturn<T>> {
  return commandsOrQueries[type](arg);
}

完整的mediator.ts代码

import {
  CreateUserCommandHandler,
  CreateUserCommand
} from "./bounded_contexts/CreateUserWithPasswordCommand";
import {
  GetUsersQueryHandler,
  GetUsersQuery
} from "./bounded_contexts/GetUsersQuery";
import {
  GetUserProfileQueryHandler,
  GetUserProfileQuery
} from "./bounded_contexts/GetUserProfileQuery";

const commandsOrQueries = {
  CREATE_USER_WITH_PASSWORD: CreateUserCommandHandler,
  GET_USERS: GetUsersQueryHandler,
  GET_USER_PROFILE: GetUserProfileQueryHandler
} as const;

type CommandOrQueryType = keyof typeof commandsOrQueries;
type Handler<T extends CommandOrQueryType> = typeof commandsOrQueries[T];
type HandlerArgs<T extends CommandOrQueryType> = Parameters<Handler<T>>[0];
type HandlerReturn<T extends CommandOrQueryType> = ReturnType<Handler<T>>;

type DispatchParams<T extends CommandOrQueryType> = {
  type: T;
  arg: HandlerArgs<T>;
};

export async function dispatch<T extends CommandOrQueryType>({ type, arg }: DispatchParams<T>): Promise<HandlerReturn<T>> {
  return commandsOrQueries[type](arg);
}

效果验证

在index.ts中调用时,TypeScript会自动完成精确的类型推断:

(async () => {
  // result自动推断为boolean
  const result = await dispatch({
    type: "CREATE_USER_WITH_PASSWORD",
    arg: {
      email: "theemail@mail.com",
      password: "the password"
    }
  });

  // result2自动推断为{ users: { id: string; name: string }[] }
  const result2 = await dispatch({
    type: "GET_USERS",
    arg: {}
  });

  // result3自动推断为{ firstName: string; lastName: string; dateOfBirth: Date }
  const result3 = await dispatch({
    type: "GET_USER_PROFILE",
    arg: {
      userId: "the user Id"
    }
  });
})();

为什么之前的方法无法自动推断返回类型

之前手动维护的Mediator联合类型,仅能约束type和arg的对应关系,但Dispatch函数的返回类型会被推断为所有处理函数返回值的联合类型,TypeScript无法根据传入的具体type精确缩小范围。而通过泛型绑定type与返回类型后,每个调用都会对应唯一的返回类型,从而实现自动推断。

内容的提问来源于stack exchange,提问作者Jose A

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:45:41