首页 > 解决方案 > 推断 API 命名空间对象的方法类型

问题描述

有两个名为user和的 API 命名空间project。我尝试创建一个可以推断 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;
}
export function useApiQuery<Params, Data>(api: ??, params: Params): UseApiQueryResponse<Data> {
  return api(params)
      .then((res: string) => ({loading: false, data: res}));
}

客户端使用:

useApiQuery(apis.user.getUser, {id: '1'});
useApiQuery(apis.project.getProject);

我如何输入api参数,它可以是任何 API 方法。最好Data根据类型推断或约束返回值类型api

打字稿游乐场

标签: typescript

解决方案


首先,您需要推断 的第一个参数useApiQuery

type AsyncFn = (...args: any[]) => Promise<any>

const useApiQuery = <Api extends AsyncFn, Data>(api: Api, ...params: Parameters<Api>) =>
  api(params)
    .then((res: string) => ({ loading: false, data: res }))
    

因为,useApiQuery返回承诺,你可以仅仅UseApiQueryResponse<Data>因为它是一个返回Promise<UseApiQueryResponse<Data>>

此外,这行代码useApiQuery(apis.user.getUser, { id: '1' })是无效的,因为getUser需要 astring而不是对象。

这是完整的示例:

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

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

type AsyncFn = (...args: any[]) => Promise<any>

const useApiQuery = <Api extends AsyncFn>(api: Api, ...params: Parameters<Api>):
  Promise<UseApiQueryResponse<ReturnType<Api>>> =>
  api(params)
    .then((res) => ({ loading: false, data: res }))


const result1 = await useApiQuery(apis.user.getUser, '42'); // UseApiQueryResponse<Promise<string>>
const result2 = await useApiQuery(apis.project.getProject); // UseApiQueryResponse<Promise<number>>

export { }

操场


推荐阅读