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

TypeScript如何定义通用useApiQuery函数的api参数类型

解决方案

你可以通过 TypeScript 内置的函数类型约束和工具泛型,实现API参数和返回值的自动推断,具体修改如下:

核心思路

  1. 用泛型约束传入的api是一个返回Promise的异步函数
  2. 用内置工具泛型自动提取API的入参类型和异步返回值类型,无需手动传入泛型参数
  3. 用剩余参数适配无参/多参的API调用场景

完整实现代码

const user = {
  async getUser(id: string): Promise<string> {
    return 'user'
  }
}
const project = {
  async getProject(): Promise<string> {
    return 'project'
  }
}
const apis = {
  user,
  project
};

interface UseApiQueryResponse<Data> {
  loading: boolean;
  data: Data | undefined;
}

// 改造后的useApiQuery函数
export function useApiQuery<T extends (...args: any[]) => Promise<any>>(
  api: T,
  // 自动提取api的入参类型,适配0个/多个参数的场景
  ...params: Parameters<T>
  // 自动提取Promise包裹的返回值类型,注意原代码实际返回的是Promise,所以返回类型要加Promise包裹
): Promise<UseApiQueryResponse<Awaited<ReturnType<T>>>> {
  return api(...params)
    .then(res => ({ loading: false, data: res }));
}

调用效果

// 自动推断入参类型必须为{id: string},返回值为Promise<UseApiQueryResponse<string>>
useApiQuery(apis.user.getUser, {id: '1'});
// 无需传参,自动推断返回值为Promise<UseApiQueryResponse<string>>
useApiQuery(apis.project.getProject);

// 类型错误场景会自动报错,比如给getUser传错误格式的参数:
// useApiQuery(apis.user.getUser, {id: 123}); // 会提示id类型不匹配

类型说明

  • T extends (...args: any[]) => Promise<any>:约束传入的api必须是返回Promise的异步函数
  • Parameters<T>:TypeScript 内置泛型,用于提取函数T的所有入参类型
  • ReturnType<T>:TypeScript 内置泛型,用于提取函数T的返回值类型
  • Awaited<>:TypeScript 4.5+内置泛型,用于提取Promise包裹的实际返回值类型,如果你使用的TS版本低于4.5,可以替换为ReturnType<T> extends Promise<infer R> ? R : never实现相同效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:18:02