为tRPC的useQuery封装带正确TypeScript类型的自定义Hook
解决tRPC封装useQuery自定义Hook的TypeScript类型问题
核心思路
要封装tRPC的useQuery,关键是精准识别仅支持查询操作的Procedure类型,通过泛型自动提取输入参数和返回值的类型,彻底替代any来保留类型提示。
类型安全的Hook实现
// 筛选出具备useQuery方法的Query Procedure类型,排除Mutation/Subscription等不兼容类型 type TrpcQueryProcedure = { useQuery: (...args: any[]) => any; }; // 自定义Hook的类型安全版本 function useCustomHook<TProc extends TrpcQueryProcedure>( procedure: TProc, input: Parameters<TProc['useQuery']>[0] ) { return procedure.useQuery(input); }
更精细化的类型推导(可选)
如果需要明确提取输入和输出的类型定义,可以进一步扩展泛型:
// 提取Query Procedure的输入参数类型 type QueryInput<TProc extends TrpcQueryProcedure> = Parameters<TProc['useQuery']>[0]; // 提取Query Procedure的返回值类型 type QueryOutput<TProc extends TrpcQueryProcedure> = ReturnType<TProc['useQuery']>; function useCustomHook<TProc extends TrpcQueryProcedure>( procedure: TProc, input: QueryInput<TProc> ): QueryOutput<TProc> { return procedure.useQuery(input); }
报错原因解析
- "TrpcProcedure无useQuery属性":你之前用了
tRPC的通用Procedure类型,它包含了Mutation、Subscription等不具备useQuery的类型,必须通过存在性检查筛选出仅支持查询的子集。 - "联合类型签名不兼容":泛型约束过于宽泛,没有限定到
useQuery的调用签名,上面的TrpcQueryProcedure通过过滤不兼容类型,避免了联合类型的冲突。
使用示例
// 调用时自动获得完整类型提示 const { data, isLoading } = useCustomHook(trpc.myendpoint, { foo: 'bar' }); // data自动匹配trpc.myendpoint的返回类型,input参数会有严格的类型校验
内容的提问来源于stack exchange,提问作者Thomas Dondorf
相关产品推荐
相关产品推荐

