如何为重写的返回Promise的Apisauce Get方法添加类型提示?
问题背景
我尝试给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

