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

如何为重写的返回Promise的Apisauce Get方法添加类型提示?

为Apisauce添加缓存层时的TypeScript类型错误解决

问题背景

我尝试给Apisauce添加缓存层,编写的代码功能正常,但抛出了TypeScript错误。

原实现代码

import {create} from 'apisauce';

import cache from '../utility/cache';

const apiClient = create({
  baseURL: 'https://randomuser.me',
});

const get = apiClient.get;

// 修改get方法
apiClient.get = async (url, params, axiosConfig) => {
  const response = await get(url, params, axiosConfig);

  if (response.ok) {
    await cache.store(url, response.data); // 缓存响应数据
    return response;
  }

  const data = await cache.get(url); // 从缓存获取数据
  return data ? {ok: true, data} : response;
};

export default apiClient;

TypeScript错误信息

src/api/client.tsx:39:1 - 错误 TS2322: 类型 '<T, U = T>(url: string, params: {} | undefined, axiosConfig: AxiosRequestConfig | undefined) => Promise<ApiErrorResponse | ApiOkResponse | { ...; }>' 无法分配给类型 '<T, U = T>(url: string, params?: {} | undefined, axiosConfig?: AxiosRequestConfig | undefined) => Promise<ApiResponse<T, U>>'。
类型 'Promise<ApiErrorResponse | ApiOkResponse | { ok: true; data: never; }>' 无法分配给类型 'Promise<ApiResponse<T, U>>'。
类型 'ApiErrorResponse | ApiOkResponse | { ok: true; data: never; }' 无法分配给类型 'ApiResponse<T, U>'。
类型 'ApiErrorResponse' 无法分配给类型 'ApiResponse<T, U>'。
类型 'ApiErrorResponse' 无法分配给类型 'ApiErrorResponse'。
类型 'unknown' 无法分配给类型 'U'。
'U' 可以被实例化为任意与 'unknown' 无关的类型。

39 apiClient.get = async (url, params, axiosConfig) => {

我的尝试代码

我尝试添加类型提示和指定返回类型,但无法正确返回ApiResponse<T, U> | PromiseLike<ApiResponse<T, U>>类型,尝试代码如下:

const get = apiClient.get
apiClient.get = async <T, U = T>(
  url: string,
  params?: {},
  axiosConfig?: AxiosRequestConfig
): Promise<ApiResponse<T, U>> => {
  const response = await get(url, params, axiosConfig)

  if (response.ok) {
    cache.store(url, response.data)
    return new Promise((resolve, reject) => {
      resolve(ApiOkResponse<response.data>)
    })
  }

  const data = await cache.get(url)
  return new Promise((resolve, reject) => {
    if (data) {
      resolve({ ok: true, data })
    }

    reject(response)
  })
}

解决方案

核心问题分析

错误根源在于:

  • 自定义返回的{ ok: true, data }未符合ApiOkResponse<T>的完整类型结构,TypeScript无法推断其与ApiResponse<T, U>匹配
  • 错误响应的泛型类型U未与原方法的约束对齐
  • 尝试代码中ApiOkResponse<response.data>的写法错误,泛型参数需传入类型而非具体值

修正后的代码

import { create, ApiResponse, ApiOkResponse, AxiosRequestConfig } from 'apisauce';
import cache from '../utility/cache';

const apiClient = create({
  baseURL: 'https://randomuser.me',
});

// 保留原get方法的类型定义
const originalGet = apiClient.get;

// 重载get方法,严格匹配原泛型约束
apiClient.get = async <T, U = T>(
  url: string,
  params?: Record<string, unknown>,
  axiosConfig?: AxiosRequestConfig
): Promise<ApiResponse<T, U>> => {
  const response = await originalGet<T, U>(url, params, axiosConfig);

  if (response.ok) {
    // 缓存时指定数据类型
    await cache.store<T>(url, response.data);
    return response;
  }

  // 从缓存获取时指定类型为T
  const cachedData = await cache.get<T>(url);
  
  if (cachedData) {
    // 构造符合ApiOkResponse<T>结构的对象,确保类型匹配
    return {
      ...response,
      ok: true,
      data: cachedData,
      problem: null,
      status: 200,
    } as ApiOkResponse<T>;
  }

  // 无缓存时返回原错误响应,确保U类型匹配
  return response as ApiResponse<T, U>;
};

export default apiClient;

关键修正点

  • 显式指定泛型参数<T, U = T>调用原originalGet方法,确保类型传递正确
  • 给缓存的get和store方法添加泛型类型<T>,保证缓存数据类型与接口返回一致
  • 构造缓存返回对象时,完整实现ApiOkResponse<T>的结构(包含problem、status等字段),避免类型推断失败
  • 使用类型断言as ApiOkResponse<T>和as ApiResponse<T, U>,帮助TypeScript确认返回值类型匹配

额外建议

确保你的cache工具类也支持泛型,示例如下:

// cache.ts示例
class Cache {
  async store<T>(key: string, data: T): Promise<void> {
    // 缓存实现逻辑
  }

  async get<T>(key: string): Promise<T | null> {
    // 获取缓存逻辑
  }
}

export default new Cache();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:40:27