TypeScript中RTK Query如何配置全局/端点自定义错误类型
RTK Query 自定义接口错误类型配置方案
问题根源
你遇到的类型报错来自两个核心问题:
- 直接对原生
fetchBaseQuery做类型断言的写法无效:原生fetchBaseQuery的返回错误是固定的联合类型,包含网络错误、解析错误等客户端侧错误场景,硬断言为自定义类型会被TS检测到结构不匹配。 - 自定义错误结构和实际返回结构不匹配:
fetchBaseQuery返回的服务端业务错误,响应体统一挂载在error.data字段下,你之前定义的CustomError把message放在错误根层级,和实际结构不符。
方案1:全局统一配置所有接口的错误类型
第一步:定义覆盖全场景的错误类型
不要只定义业务错误结构,需要同时覆盖客户端侧请求异常(断网、超时、跨域等):
// 服务端返回的业务错误结构 type ApiBusinessError = { data: { message: string; // 可扩展其他业务错误字段,比如错误码、错误详情等 }; status: number; }; // 客户端侧请求异常 type ApiRequestError = { status: "FETCH_ERROR"; error: string; }; // 全局统一错误类型 export type CustomError = ApiBusinessError | ApiRequestError;
第二步:包装基础请求方法,声明正确类型
不要直接断言原生fetchBaseQuery,加一层包装显式指定类型,还可以在这层加全局统一的错误处理逻辑(比如401自动跳登录、错误提示统一弹出等):
import { createApi, fetchBaseQuery, BaseQueryFn, FetchArgs } from '@reduxjs/toolkit/query/react'; const rawBaseQuery = fetchBaseQuery({ baseUrl: "https://...", prepareHeaders: (headers) => { const token = localStorage.getItem("token"); if (token) { headers.set("Authorization", `Bearer ${token}`); } return headers; }, }); // 显式声明包装后baseQuery的错误类型为自定义的CustomError const baseQuery: BaseQueryFn<string | FetchArgs, unknown, CustomError, {}> = async (args, api, extraOptions) => { const result = await rawBaseQuery(args, api, extraOptions); // 可在这里加全局错误处理逻辑 return result; }; export const apiSlice = createApi({ reducerPath: "api", baseQuery: baseQuery, endpoints: () => ({}), });
使用时的类型安全调用
配置完成后,所有自动生成的query、mutation hook返回的error都会被推导为CustomError类型,只要做简单的类型收窄就能安全访问字段:
const [login, { error }] = useLoginMutation(); // 收窄为业务错误类型 if (error && "data" in error) { // TS会自动推导error为ApiBusinessError类型,可安全访问data.message alert(error.data.message); } // 收窄为网络错误类型 if (error && error.status === "FETCH_ERROR") { alert(`请求异常:${error.error}`); }
方案2:给单个端点指定独立错误类型
如果部分接口的错误结构和全局结构不一致,可以在定义endpoint时单独指定错误类型,不需要修改全局配置:
// 登录接口独有的错误结构 type LoginApiError = { data: { message: string; code: number; remainAttempts?: number; // 剩余密码重试次数等独有字段 }; status: number; }; export const authApi = apiSlice.injectEndpoints({ endpoints: (builder) => ({ // 第三个泛型参数传入自定义错误类型 login: builder.mutation<LoginRes, LoginParams, { error: LoginApiError }>({ query: (params) => ({ url: "/auth/login", method: "POST", body: params, }), }), }), });
配置后useLoginMutation返回的error会优先使用LoginApiError类型,不影响其他接口的全局类型。
内容的提问来源于stack exchange,提问作者Abhi
相关产品推荐
相关产品推荐

