NOTE: This now works fine in RTKQuery v2 as it has been rewritten to TypeScript. Original question below.
Short description
I'm trying to compile below piece of TypeScript code. Tsc
isn't satisfied with my return type from the queryFn function. Am I doing something wrong or am I missing something?
The code
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;
The error
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<...>'
Bad workaround
Looking at the examples on the internet I am able to compile this code when I remove types from build.query
to make this enpoint like this:
getUser: build.query({ // changed here
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`);
},
}),
But then I lose strong typing everywhere in my code which makes this workaround at least controversial.
BaseResponse
? – Earleenearlene