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

解决递归函数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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:21:07