如何在Redux Toolkit Query中用自定义injectGetItems生成可自动补全查询钩子?
解决方案
核心问题在于原实现中TypeScript无法捕获端点名称的具体字面量类型,也无法关联钩子与查询的参数/返回值类型。以下是修复后的完整实现:
关键修改点
- 将端点名称设为泛型字面量类型,让TypeScript保留
name参数的具体字符串值,而非宽泛的string类型 - 精确定义返回类型,结合模板字符串类型与RTK Query内置类型,生成与端点匹配的钩子类型
- 添加类型断言确保类型安全,在标签和返回对象上使用
as const或类型断言,避免类型拓宽
修复后的代码
import { baseApi } from '../api'; import type { EndpointBuilder } from '@reduxjs/toolkit/query/react'; // 根据端点名称生成对应的useXxxQuery钩子类型 type InjectGetItemsReturn<T extends string, Response, Args> = { [K in `use${Capitalize<T>}Query`]: ReturnType< EndpointBuilder<any, any, any>['query']<Response, Args> >['useQuery']; }; export const injectGetItems = <T extends string, ApiResponse, ApiArgs = void>( name: T, tag: string, url: string, ): InjectGetItemsReturn<T, ApiResponse, ApiArgs> => { const enhancedApi = baseApi.enhanceEndpoints({ addTagTypes: [tag] }); const entityApi = enhancedApi.injectEndpoints({ endpoints: (builder) => ({ [name]: builder.query<ApiResponse, ApiArgs>({ query: () => url, providesTags: (result) => Array.isArray(result) ? [ ...result.map((item) => ({ type: tag, id: item.id } as const)), { type: tag, id: 'LIST' } as const, ] : [{ type: tag, id: 'LIST' } as const], }), }), overrideExisting: false, // 防止意外覆盖已有端点 }); // 类型断言确保TypeScript识别钩子的名称与类型 return { [`use${Capitalize(name)}Query`]: entityApi.endpoints[name].useQuery, } as InjectGetItemsReturn<T, ApiResponse, ApiArgs>; };
细节说明
- 泛型端点名称:
T extends string让TypeScript记住传入的具体字符串(比如'getCharacter'),为生成useGetCharacterQuery提供类型依据 - 返回类型关联:
InjectGetItemsReturn通过模板字符串生成钩子名称,并直接关联RTK Query的query方法返回的useQuery类型,确保钩子的参数和返回值完全匹配ApiResponse和ApiArgs as const断言:在providesTags中使用as const,让TypeScript识别标签的具体结构,避免被推断为宽泛的object类型,提升类型检查的准确性overrideExisting配置:防止注入端点时意外覆盖已存在的端点,避免潜在的bug
验证用法
export const { useGetCharacterQuery } = injectGetItems<'getCharacter', CharacterResponse, void>( 'getCharacter', TAG_TYPES.rickAndMorty, QUERY_URL.rickandmorty_character );
现在IDE会正确推断useGetCharacterQuery的类型,支持参数和返回值的自动补全。
内容的提问来源于stack exchange,提问作者Jono
相关产品推荐
相关产品推荐

