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

如何为useModel Hook根据方法类型正确定义第三个参数类型

解决useModel Hook中参数类型随方法动态匹配的问题

要让useModel的第三个参数能根据传入的method自动匹配对应方法的参数类型,我们可以通过类型映射和条件类型实现类型约束,同时修正Hook内部的调用逻辑,以下是具体方案:

1. 定义方法与参数类型的映射关系

先为BaseApiModel的静态方法创建参数类型映射,把每个方法的参数转换成调用useModel时传入的options结构:

// 定义各方法对应的options类型
type ModelMethodOptions<T extends typeof BaseApiModel> = {
  get: { id?: number; params?: QueryFilterParams };
  post: { data: Omit<InstanceType<T>, "id"> };
  // 按需补充put/patch/delete等其他方法的参数类型
};

// 提取所有支持的方法名
type Methods = keyof ModelMethodOptions<any>;

这里InstanceType<T>用来获取模型类(比如Art)的实例类型,Omit<InstanceType<T>, "id">正好对应post方法需要的参数类型。

2. 修改useModel的类型定义与逻辑

调整useModel的泛型和参数类型,让options的类型随method动态变化,同时修正函数调用逻辑(避免方法被立即执行):

function useModel<T extends typeof BaseApiModel, M extends Methods>(
  model: T,
  method: M,
  options?: ModelMethodOptions<T>[M]
) {
  // 处理get方法的查询逻辑
  if (method === "get") {
    const { id, params } = options || {};
    return useQuery({
      queryKey: [model.key, method, id, params],
      queryFn: () => model.get(id, params),
      enabled: true,
    });
  }

  // 处理post等mutation方法的逻辑
  const mutationFn = async () => {
    switch (method) {
      case "post":
        return model.post((options as ModelMethodOptions<T>["post"]).data);
      // 按需补充put/patch/delete等方法的处理逻辑
      default:
        throw new Error(`Unsupported method: ${method}`);
    }
  };

  return useMutation({
    mutationKey: [model.key, method, options],
    mutationFn,
  });
}

3. 关键优化点说明

  • 动态类型匹配:通过ModelMethodOptions<T>[M],当传入不同method时,options会自动匹配对应类型——比如传入"get"时只能传{ id?: number; params?: QueryFilterParams },传入"post"时只能传{ data: Omit<Art, "id"> }。
  • 修正函数调用:之前直接写queryFn: model[method](options)会立即执行方法,改成() => model.get(id, params)才符合useQuery的要求(queryFn需要是返回Promise的函数)。
  • 类型安全校验:通过类型约束,编辑器会自动提示参数错误,比如给post方法传带id的data时会直接报错。

测试调用示例

现在调用useModel时,类型系统会自动做校验:

// 正确:get方法接受id和params参数
useModel(Art, "get", { id: 7 });
// 正确:post方法的data符合Omit<Art, "id">类型
useModel(Art, "post", { data: { title: "Art title", description: "test" } });
// 错误:post方法的data不能包含id,编辑器会直接报错
useModel(Art, "post", { data: { id: 1, title: "Art title" } });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:42:45