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

RTK Query实现重授权时TypeScript报错:accessToken不存在于类型{}

解决RTK Query重授权中的TypeScript类型错误

问题场景

我正尝试按照RTK Query官方文档实现重授权功能,后端返回的对象结构为:

{
  user: IUser,
  accessToken: string
}

但代码中标记的行出现TypeScript错误:Property 'accessToken' does not exist on type '{}',相关代码如下:

const baseQuery = fetchBaseQuery({
  baseUrl: 'http://localhost:5000/api/',
  credentials: 'include',
  prepareHeaders: headers => {
    headers.set(
      'authorization',
      `Bearer ${localStorage.getItem('bearer-token')}`
    )
    return headers
  },
})

const baseQueryWithReauth: BaseQueryFn<
  string | FetchArgs,
  unknown,
  FetchBaseQueryError
> = async (args, api, extraOptions) => {
  let result = await baseQuery(args, api, extraOptions)
  if (result.error && result.error.status === 401) {
    // try to get a new token
    const refreshResult = await baseQuery('auth/refresh', api, extraOptions)
    if (refreshResult.data) {
      // store the new token
      console.log('refreshResult.data:', refreshResult.data)

      if (refreshResult.data.hasOwnProperty('accessToken')) {
        // 错误行
        localStorage.setItem('bearer-token', refreshResult.data.accessToken)
      }
      // retry the initial query
      result = await baseQuery(args, api, extraOptions)
    } else {
      // api.dispatch(())
    }
  }
  return result
}

解决方案

TypeScript报错的核心原因是无法推断refreshResult.data的具体类型,默认将其视为unknown或空对象类型,因此不允许直接访问accessToken属性。以下是几种可行的解决方式:

1. 使用类型断言明确类型

先定义后端返回的类型,再通过类型断言告诉TypeScript数据的结构:

// 定义刷新接口的返回类型
interface AuthRefreshResponse {
  user: IUser;
  accessToken: string;
}

// 在错误行处添加类型断言
if (refreshResult.data.hasOwnProperty('accessToken')) {
  localStorage.setItem('bearer-token', (refreshResult.data as AuthRefreshResponse).accessToken)
}

2. 编写类型守卫函数(更安全)

通过类型守卫函数校验数据结构,既满足TypeScript的类型检查,又能在运行时确保数据的合法性:

interface AuthRefreshResponse {
  user: IUser;
  accessToken: string;
}

// 类型守卫函数
function isAuthRefreshResponse(data: unknown): data is AuthRefreshResponse {
  return (
    typeof data === 'object' &&
    data !== null &&
    'accessToken' in data &&
    typeof (data as AuthRefreshResponse).accessToken === 'string'
  );
}

// 替换原有的hasOwnProperty判断
if (isAuthRefreshResponse(refreshResult.data)) {
  localStorage.setItem('bearer-token', refreshResult.data.accessToken)
}

3. 给BaseQueryFn指定正确的泛型参数

修改baseQueryWithReauth的泛型定义,明确指定接口可能返回的数据类型:

interface AuthRefreshResponse {
  user: IUser;
  accessToken: string;
}

const baseQueryWithReauth: BaseQueryFn<
  string | FetchArgs,
  AuthRefreshResponse | unknown, // 包含刷新接口的返回类型
  FetchBaseQueryError
> = async (args, api, extraOptions) => {
  // ... 原有代码逻辑
}

内容的提问来源于stack exchange,提问作者Victor Mog

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:32:50