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
相关产品推荐
相关产品推荐

