解决递归函数checkAccessToken的TypeScript隐式any返回类型错误
修复TypeScript递归函数隐式返回类型错误及认证系统优化建议
错误原因与修复方案
这个TypeScript错误是因为递归函数checkAccessToken未显式声明返回类型,TypeScript处理递归引用时无法自动推断准确类型,必须手动指定返回类型。
步骤1:定义返回数据类型
根据后端check-access-token接口的实际返回结构,定义对应的TypeScript类型:
// 示例结构,根据你的后端接口调整字段 interface AccessTokenCheckResponse { valid: boolean; // 其他返回字段,比如expiresAt等 }
步骤2:为函数添加显式返回类型
修改checkAccessToken和refreshAccessToken函数,明确返回类型:
import { API_BASE_URI } from './your-api-config'; // 确保导入正确的API地址配置 export const refreshAccessToken = async (): Promise<boolean> => { const response = await fetch( `${API_BASE_URI}/api/auth/refresh-access-token`, { method: "POST", credentials: "include", } ); if (!response.ok) { return false; } const returnData = await response.json(); localStorage.setItem("accessToken", returnData.accessToken); return true; }; export const checkAccessToken = async (): Promise<AccessTokenCheckResponse> => { const accessToken = localStorage.getItem("accessToken"); // 提前处理token不存在的情况 if (!accessToken) { throw new Error("Access token not found"); } const response = await fetch(`${API_BASE_URI}/api/auth/check-access-token`, { method: "POST", headers: { "Content-type": "application/json", Authorization: `Bearer ${accessToken}`, }, }); if (response.status === 401) { const result = await refreshAccessToken(); if (!result) { throw new Error("Error while refreshing access token"); } // 递归调用,此时已更新accessToken return checkAccessToken(); } if (!response.ok) { throw new Error("Error while checking access token"); } const data = await response.json(); return data as AccessTokenCheckResponse; };
额外的认证系统优化建议
限制递归重试次数:当前代码若刷新token后再次校验仍返回401,会无限递归导致栈溢出,建议添加重试次数限制:
export const checkAccessToken = async (retryCount = 0): Promise<AccessTokenCheckResponse> => { const MAX_RETRIES = 1; // 最多重试1次(即仅刷新一次token) if (retryCount >= MAX_RETRIES) { throw new Error("Max refresh retries exceeded"); } // ... 原有代码 ... if (response.status === 401) { const result = await refreshAccessToken(); if (!result) { throw new Error("Error while refreshing access token"); } return checkAccessToken(retryCount + 1); // 递增重试次数 } // ... 原有代码 ... };避免并发请求重复刷新token:多个请求同时触发
checkAccessToken会重复调用refresh接口,可通过全局Promise锁控制:let refreshPromise: Promise<boolean> | null = null; export const refreshAccessToken = async (): Promise<boolean> => { if (refreshPromise) { return refreshPromise; // 若正在刷新,直接返回现有Promise } refreshPromise = (async () => { try { const response = await fetch( `${API_BASE_URI}/api/auth/refresh-access-token`, { method: "POST", credentials: "include" } ); if (!response.ok) return false; const returnData = await response.json(); localStorage.setItem("accessToken", returnData.accessToken); return true; } finally { refreshPromise = null; // 刷新完成后清空锁 } })(); return refreshPromise; };统一拦截器替代手动调用:可以封装fetch或使用axios拦截器,统一处理请求前的token校验和刷新,无需在每次操作时手动调用
checkAccessToken,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者yzkael
相关产品推荐
相关产品推荐

