TypeScript如何定义通用useApiQuery函数的api参数类型
解决方案
你可以通过 TypeScript 内置的函数类型约束和工具泛型,实现API参数和返回值的自动推断,具体修改如下:
核心思路
- 用泛型约束传入的
api是一个返回Promise的异步函数 - 用内置工具泛型自动提取API的入参类型和异步返回值类型,无需手动传入泛型参数
- 用剩余参数适配无参/多参的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
相关产品推荐
相关产品推荐

