如何为RTK Query/Mutation的EndpointDefinitions定义自定义参数类型?
原有可运行代码
export const reducerPath = 'api'; export const baseQuery = fetchBaseQuery({ baseUrl: BASE_URL }); export type QueryApiBuilderType = InjectedEndpointBuilder<typeof baseQuery, typeof reducerPath>; export type InjectedEndpointBuilder<T extends BaseQueryFn, U extends string> = EndpointBuilder<T, never, U>; export const createTransformedQueryEndpoint = <T, U = void>(build: QueryApiBuilderType, queryFetchArgs: FetchArgs) => build.query<T, U>({ query: () => queryFetchArgs, transformResponse: (response: { payload: T }) => response.payload }); export const createTransformedMutationEndpoint = <T, U>(build: QueryApiBuilderType, queryFetchArgs: FetchArgs) => build.mutation<T, U>({ query: (args) => ({ body: args, ...queryFetchArgs }), transformResponse: (response: { payload: T }) => response.payload }); export interface IBaseItem { id: number; title: string; } export interface IItemResponse extends IBaseItem { fullText: string; } export const itemsApi = (build: QueryApiBuilderType, url = '/item') => ({ getItems: createTransformedQueryEndpoint<IItemResponse[]>(build, { url }), createItem: createTransformedMutationEndpoint<IItemResponse, IBaseItemResponse>(build, { url, method: 'POST' }) }); const baseApi = createApi({ reducerPath, baseQuery: fetchBaseQuery({ baseUrl: BASE_URL }), endpoints: () => ({}) }); export const api = baseApi.injectEndpoints({ endpoints: (build) => ({ ...itemsApi(build) }) }); export const { useGetItemsQuery, useCreateItemMutation } = api;
修改后的代码(添加路由参数、查询参数后)
// modified createTransformedMutationEndpoint and createTransformedQueryEndpoint export const createTransformedQueryEndpoint = <T, U extends { id?: string | number; params?: object } = never>( build: QueryApiBuilderType, queryFetchArgs: FetchArgs ): EndpointDefinition<U, typeof baseQuery, string, T, typeof reducerPath> => build.query<T, U>({ query: ({ id, params, ...restQueryFetchArgs }) => ({ url: `${queryFetchArgs.url}/${id}`, params, ...restQueryFetchArgs }), transformResponse: (response: { payload: T }) => response.payload }); export const createTransformedMutationEndpoint = <T, U extends { id?: string | number; params?: object } = never>( build: QueryApiBuilderType, queryFetchArgs: FetchArgs ): EndpointDefinition<U, typeof baseQuery, string, T, typeof reducerPath> => build.mutation<T, U>({ query: ({ id, params, ...restQueryFetchArgs }) => ({ url: `${queryFetchArgs.url}/${id}`, params, body: restQueryFetchArgs, ...restQueryFetchArgs }), transformResponse: (response: { payload: T }) => response.payload }); export const itemsApi = (build: QueryApiBuilderType, url = '/item') => ({ getItems: createTransformedQueryEndpoint<IItemResponse[]>(build, { url }), getItem: createTransformedQueryEndpoint<IItemResponse>(build, { url }), // added for id routeParam example createItem: createTransformedMutationEndpoint<IItemResponse, IBaseItem>(build, { url, method: 'POST' }) }); export const api = baseApi.injectEndpoints({ endpoints: (build) => ({ ...itemsApi(build) // ERROR 1 }) }); export const { useGetItemsQuery, useGetItemQuery, useCreateItemMutation } = api; // ERROR 2
错误信息
ERROR 1
类型 { getItems: EndpointDefinition<never, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, string, IItemResponse[], "api">; getItem: EndpointDefinition<...>; createItem: EndpointDefinition<...>; } 无法分配给类型 EndpointDefinitions。
属性 getItems 与索引签名不兼容。
类型 EndpointDefinition<never, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, string, IItemResponse[], "api"> 无法分配给类型 EndpointDefinition<any, any, any, any, string>。
类型 EndpointDefinitionWithQuery<never, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, IItemResponse[]> & { ...; } & { ...; } & QueryExtraOptions<...> 无法分配给类型 EndpointDefinition<any, any, any, any, string>。
类型 EndpointDefinitionWithQuery<never, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, IItemResponse[]> & { ...; } & { ...; } & QueryExtraOptions<...> 无法分配给类型 EndpointDefinitionWithQuery<any, any, any> & { [resultType]?: any; [baseQuery]?: any; } & { extraOptions?: unknown; } & QueryExtraOptions<any, any, any, any, string>。
类型 EndpointDefinitionWithQuery<never, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, IItemResponse[]> & { ...; } & { ...; } & QueryExtraOptions<...> 无法分配给类型 QueryExtraOptions<any, any, any, any, string>。
属性 providesTags 的类型不兼容。
类型 ResultDescription<string, IItemResponse[], never, FetchBaseQueryError, FetchBaseQueryMeta | undefined> | undefined 无法分配给类型 ResultDescription<any, any, any, any, any> | undefined。
类型 GetResultDescriptionFn<string, IItemResponse[], never, FetchBaseQueryError, FetchBaseQueryMeta | undefined> 无法分配给类型 ResultDescription<any, any, any, any, any> | undefined。
类型 GetResultDescriptionFn<string, IItemResponse[], never, FetchBaseQueryError, FetchBaseQueryMeta | undefined> 无法分配给类型 GetResultDescriptionFn<any, any, any, any, any>。
类型 any 无法分配给类型 never。ts(2322)
apiTypes.d.ts(29, 20): 预期类型来自此签名的返回类型。
ERROR 2
类型 Api<BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, EndpointDefinitions, "api", never, unique symbol | unique symbol> 上不存在属性 useGetItemQuery。
类型 Api<BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, EndpointDefinitions, "api", never, unique symbol | unique symbol> 上不存在属性 useCreateItemMutation。
类型 Api<BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, EndpointDefinitions, "api", never, unique symbol | unique symbol> 上不存在属性 useGetItemsQuery。
内容的提问来源于stack exchange,提问作者Nikolai

