简短描述
我正在尝试编译下面的TypeScript代码。Tsc
对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<...>'
坏方法
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({ // 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`);
},
}),
但是我的代码中到处都失去了强类型,这使得这个解决方法至少引起了争议。
我最终得到了这段代码,但我不确定这是否是推荐的方法。在调用baseQuery
之后,有很多事情要做,只是为了满足编译器:
import { baseApi } from '../../../api/baseApi';
import { BaseResponse } from '../../../api/baseApiTypes';
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.tokens)
return { error: { error: `UNAUTHORIZED`, status: `CUSTOM_ERROR` } };
const result = await baseQuery(`/user/me`);
if (result.error)
return { error: result.error };
const baseResponseWithUser = result.data as BaseResponse<UserResponse>;
if (!baseResponseWithUser.data)
return { error: { error: `UNKNOWN_ERROR`, status: `CUSTOM_ERROR` } };
return { data: baseResponseWithUser.data };
},
}),
}),
});
export const { useGetUserQuery, useLazyGetUserQuery } = extendedApi;
我遵循https://redux-toolkit.js.org/rtk-query/usage-with-typescript#typing-a-basequery,所以我有一个QueryReturnValue
类型
export type QueryReturnValue<T = unknown, E = unknown, M = unknown> =
| {
error: E
data?: undefined
meta?: M
}
| {
error?: undefined
data: T
meta?: M
}
然后在queryFn
中,我执行以下操作来解决TS编译错误。
const result = await baseQuery(`/user/me`);
return result as QueryReturnValue<UserResponse, unknown, unknown>;
我所做的是创建一个辅助函数来减少冗长。
// Somewhere all api slices can import
export function someHelperForTS<T>(result: QueryReturnValue<unknown, unknown, unknown>) {
return result as QueryReturnValue<T, unknown, unknown>;
}
// Within queryFn
const result = await baseQuery(`/user/me`);
return someHelperForTS<UserResponse>(result);
我不喜欢它,因为我必须在两个构建中声明相同的响应类型。查询(build.query<UserResponse
)和someHelperForTS (someHelperForTS<UserResponse>
).