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

RTKQuery queryFn结合TypeScript使用问题(v2已修复)

RTK Query TypeScript 类型错误解决方案

注意事项

RTKQuery v2 已完全重写为 TypeScript,此类型问题现已自动修复。以下为旧版本中的原始问题及解决方案。

原始问题

我用 TypeScript 编写了 RTK Query 的扩展接口,编译时 queryFn 的返回类型始终不匹配,代码如下:

import { FetchBaseQueryError } from '@reduxjs/toolkit/dist/query/fetchBaseQuery';
import { baseApi } from '../../../api/baseApi';
import { RootState } from '../../../redux/store';
import { UserResponse } from './userApiTypes';

export const extendedApi = baseApi.injectEndpoints({
    endpoints: build => ({
        getUser: build.query<UserResponse, void>({
            queryFn: async (arg, api, extraOptions, baseQuery) => {
                const state = api.getState() as RootState;

                if (!state.auth.loginToken && !state.auth.refreshToken)
                    return { error: { error: `UNAUTHORIZED`, status: `CUSTOM_ERROR` } as FetchBaseQueryError };

                return await baseQuery(`/user/me`);
            },
        }),
    }),
});

export const { useGetUserQuery, useLazyGetUserQuery } = extendedApi;

编译错误信息

Type '(arg: void, api: BaseQueryApi, extraOptions: any, baseQuery: (arg: string | FetchArgs) => Promise<QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>>) => Promise<...>' is not assignable to type '(arg: void, api: BaseQueryApi, extraOptions: any, baseQuery: (arg: string | FetchArgs) => Promise<QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>>) => MaybePromise<...>'.
  Type 'Promise<QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>>' is not assignable to type 'MaybePromise<QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>>'.
    Type 'Promise<QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>>' is not assignable to type 'PromiseLike<QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>>'.
      Types of property 'then' are incompatible.
        Type '<TResult1 = QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>, TResult2 = never>(onfulfilled?: ((value: QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>) => TResult1 | PromiseLike<...>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | ... 1 more ......' is not assignable to type '<TResult1 = QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>, TResult2 = never>(onfulfilled?: ((value: QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>) => TResult1 | PromiseLike<...>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | ... 1 more ... | undefined...'.
          Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
            Types of parameters 'value' and 'value' are incompatible.
              Type 'QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>' is not assignable to type 'QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>'.
                Type '{ error?: undefined; data: unknown; meta?: FetchBaseQueryMeta | undefined; }' is not assignable to type 'QueryReturnValue<UserResponse, FetchBaseQueryError, unknown>'.
                  Type '{ error?: undefined; data: unknown; meta?: FetchBaseQueryMeta | undefined; }' is not assignable to type '{ error?: undefined; data: UserResponse; meta?: unknown; }'.
                    Types of property 'data' are incompatible.
                      Type 'unknown' is not assignable to type 'UserResponse'.ts(2322)
endpointDefinitions.d.ts(37, 5): The expected type comes from property 'queryFn' which is declared here on type 'Omit<EndpointDefinitionWithQuery<void, (args: string | FetchArgs, api: BaseQueryApi, extraOptions: any) => Promise<QueryReturnValue<unknown, FetchBaseQueryError, FetchBaseQueryMeta>>, UserResponse> & { ...; } & { ...; } & QueryExtraOptions<...>, "type"> | Omit<...>'

临时解决方法(不推荐)

移除 build.query 的泛型类型声明后可以编译,但会丢失全局强类型校验:

getUser: build.query({ // 移除了<UserResponse, void>泛型
            queryFn: async (arg, api, extraOptions, baseQuery) => {
                const state = api.getState() as RootState;

                if (!state.auth.loginToken && !state.auth.refreshToken)
                    return { error: { error: `UNAUTHORIZED`, status: `CUSTOM_ERROR` } as FetchBaseQueryError };

                return await baseQuery(`/user/me`);
            },
        }),

正确解决方案

问题核心是 baseQuery 返回的 data 类型为 unknown,无法自动推导为 UserResponse,以下两种方法可解决:

方案1:给 baseQuery 结果添加类型断言

先导入 QueryReturnValue 类型:

import { QueryReturnValue } from '@reduxjs/toolkit/dist/query';

再修改 queryFn 中的返回逻辑:

getUser: build.query<UserResponse, void>({
    queryFn: async (arg, api, extraOptions, baseQuery) => {
        const state = api.getState() as RootState;

        if (!state.auth.loginToken && !state.auth.refreshToken)
            return { error: { error: `UNAUTHORIZED`, status: `CUSTOM_ERROR` } as FetchBaseQueryError };

        // 给 baseQuery 返回结果添加类型断言
        return (await baseQuery(`/user/me`)) as QueryReturnValue<UserResponse, FetchBaseQueryError, FetchBaseQueryMeta>;
    },
}),

方案2:显式指定 queryFn 的返回类型

同样需要先导入 QueryReturnValue,然后给 queryFn 声明返回类型:

getUser: build.query<UserResponse, void>({
    // 显式指定 queryFn 的返回类型
    queryFn: async (arg, api, extraOptions, baseQuery): Promise<QueryReturnValue<UserResponse, FetchBaseQueryError, FetchBaseQueryMeta>> => {
        const state = api.getState() as RootState;

        if (!state.auth.loginToken && !state.auth.refreshToken)
            return { error: { error: `UNAUTHORIZED`, status: `CUSTOM_ERROR` } as FetchBaseQueryError };

        return await baseQuery(`/user/me`);
    },
}),

方案3:升级到 RTK Query v2

如开头所述,RTKQuery v2 已完全重写为 TypeScript,类型推导逻辑更完善,无需额外处理即可自动匹配类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:00:57