我正在从通用函数中对axios.get的调用返回AxiosResponse对象.该物体的形状如下:

interface AxiosResponse<T = any, D = any> {
  data: T;
  ...
}

get电话有这种类型:

get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;

我花了几个小时寻找解决这个错误的答案:

"Property 'data' does not exist on type 'Awaited<R>

在此代码中(标记错误位置):

export const fetchWithRetry = async <
  T = any,
  Q = Record<string, string>,
  R = AxiosResponse<T>
>(
  route: string,
  queryParams: Partial<Q> = {},
) => {
  const response = await fetchResponseWithRetry<T, Q, R>(route, queryParams)
  return response.data; // <= ERROR IS HERE
};

export const fetchResponseWithRetry = async <
  T = any,
  Q = Record<string, string>,
  R = AxiosResponse<T>,
>(
  route: string,
  queryParams: Partial<Q> = {},
) => {
  try {
    const options: AxiosRequestConfig = {
      headers: {
        "Content-Type": "application/json",
      },
      params: <Q>{ ...queryParams },
    };
    return (await axios.get<T, R, unknown>(route, options));
  } catch (error) {
    if (error instanceof Error) {
      buildLogger(`${error.message}`);
      if (error instanceof AxiosError) buildLogger(`${error.request.url}`);
    }
  }
  throw new Error(`This should never be reached.`);
};

据我了解,4.5中添加了Awaited<R>类型.我从other answers中了解到,Awaited类型应该解开为R(来自对该问题的公认答案):

如果您正在等待的类型TPromise<U>,而U不是任何类型的Promise,那么Awaited<T>U相同

我该如何解决这个问题?

推荐答案

这里的问题是,您自定义了R类型,这意味着响应实际上可以是任何内容,因此Typescript无法保证它具有data属性.

除了T响应数据类型之外,实际上不需要为任何类型提供一般性.

此代码工作时没有任何错误,并且还消除了一些其他小问题

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const fetchWithRetry = async <T = any,>(
  route: string,
  queryParams: Record<string, string> = {},
) => {
  const response = await fetchResponseWithRetry<T>(route, queryParams);
  return response.data;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const fetchResponseWithRetry = async <T = any,>(
  route: string,
  queryParams: Record<string, string> = {},
) => {
  try {
    // GET requests do not have a body so no content-type required
    const options: AxiosRequestConfig = {
      params: queryParams,
    };
    return await axios.get<T>(route, options);
  } catch (error) {
    if (error instanceof Error) {
      buildLogger(`${error.message}`);
      if (axios.isAxiosError(error)) {
        // use the provided type guard method
        buildLogger(`${error.request.url}`);
      }
    }
  }
  throw new Error(`This should never be reached.`);
};

如果您真的想保留R的通用性,则应该使用extends而不是默认值.

R extends { data: T } = AxiosResponse<T>

Typescript相关问答推荐

如何修复VueJS中的val类型不能赋给函数

如何将绑定到实例的类方法复制到类型脚本中的普通对象?

在NextJS中获得Spotify Oauth,但不工作'

打印脚本丢失函数的泛型上下文

有没有办法解决这个问题,类型和IntrinsicAttributes类型没有相同的属性?

我可以使用TypeScrip从字符串词典/记录中填充强类型的环境对象吗?

被推断为原始类型的交集的扩充类型的交集

Select 下拉菜单的占位符不起作用

如何编写在返回函数上分配了属性的类型安全泛型闭包

在React中定义props 的不同方式.FunctionalComponent

为什么&Quot;元素隐式具有';Any';类型,因为...即使我已经打字了,也不能作为索引显示错误吗?

在构建Angular 应用程序时,有没有办法通过CLI传递参数?

使用来自API调用的JSON数据的Angular

如何将通用接口的键正确设置为接口的键

字符串文字联合的分布式条件类型

垫子工具栏不起作用的Angular 布线

使用&reaction测试库&如何使用提供程序包装我的所有测试组件

Typescript 是否可以区分泛型参数 void?

基于可选参数的动态类型泛型类型

const 使用条件类型时,通用类型参数不会推断为 const