首页
/ ts-rest项目中React组件与AppRouter的泛型集成实践

ts-rest项目中React组件与AppRouter的泛型集成实践

2025-06-28 09:34:54作者:曹令琨Iris

背景介绍

在React应用开发中,我们经常需要创建可复用的通用组件,这些组件需要与后端API进行交互。ts-rest作为一个类型安全的API契约库,能够帮助我们更好地管理前端与后端的通信。然而,在实际开发中,将ts-rest与React组件结合使用时,特别是在处理泛型组件和AppRouter时,开发者可能会遇到类型定义上的挑战。

核心问题分析

当尝试创建一个通用的React组件,该组件需要接收一个ts-rest路由作为属性(prop)时,我们面临的主要困难是如何正确定义组件的类型。具体来说,我们需要:

  1. 确保组件能够接受不同类型的ts-rest路由
  2. 在组件内部正确使用这些路由的方法,如useInfiniteQuery
  3. 保持完整的类型安全性和IDE智能提示

解决方案探索

方案一:直接传递路由属性

最初的想法可能是直接在组件属性中传递路由,如:

interface Props {
  keys: QueryKey;
  route: ???; // 类型定义困难
}

然而,这种方法会遇到类型定义困难的问题,因为ts-rest的路由类型较为复杂,难以直接作为属性类型使用。

方案二:使用路径字符串标识路由

更可行的方案是使用路径字符串来标识路由,同时传递完整的contract和client:

<MyComponent 
  queryKey={["products"]} 
  contract={contract} 
  client={client} 
  route="products.list" 
  args={...} 
/>

这种方式的优势在于:

  1. 避免了直接处理复杂的路由类型
  2. 保持了类型安全性
  3. 使用起来更加直观

实现细节

路径类型定义

我们可以借鉴其他库的经验,定义一个能够深度遍历对象路径的类型:

type Path<T> = T extends object
  ? { [K in keyof T]: `${Exclude<K, symbol>}${Path<T[K]> extends never 
      ? '' 
      : '.'}${Path<T[K]>}` }[keyof T]
  : never;

这个类型可以帮助我们确保route属性只能是contract中存在的有效路径。

请求参数类型推断

对于args属性,我们可以使用ts-rest提供的ClientInferRequest工具类型来确保传递的参数与API契约匹配:

type RequestArgs = ClientInferRequest<typeof contract.products.list>;

组件内部实现

在组件内部,我们可以通过路径字符串来动态获取对应的路由方法。虽然这会导致一些类型推断的困难,但可以通过类型断言或@ts-expect-error来暂时绕过:

export function MyComponent({queryKey, contract, client, route, args}) {
  // 动态获取路由方法
  const routeFn = getRouteFromPath(client, route);
  
  // @ts-expect-error 类型推断困难
  const infiniteQuery = routeFn.useInfiniteQuery(
    queryKey,
    ({ pageParam = 1 }) => ({
      query: { page: Number(pageParam) },
      ...args
    })
  );
  
  // 组件渲染逻辑...
}

最佳实践建议

  1. 保持组件接口简洁:尽量使用路径字符串而非直接传递路由对象
  2. 合理使用类型工具:充分利用ts-rest提供的类型工具如ClientInferRequest
  3. 适度使用类型断言:在确实难以类型推断的地方,可以使用@ts-expect-error
  4. 文档和注释:为复杂组件添加详细注释,说明预期的使用方式

总结

将ts-rest与React组件结合使用时,通过路径字符串而非直接传递路由对象的方式,可以更优雅地解决类型定义问题。虽然组件内部可能需要一些类型断言,但对外提供了简洁、类型安全的接口。这种方法既保持了ts-rest的类型安全优势,又提供了良好的开发者体验。

登录后查看全文
热门项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
22
6
docsdocs
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
192
2.15 K
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
9
1
金融AI编程实战金融AI编程实战
为非计算机科班出身 (例如财经类高校金融学院) 同学量身定制,新手友好,让学生以亲身实践开源开发的方式,学会使用计算机自动化自己的科研/创新工作。案例以量化投资为主线,涉及 Bash、Python、SQL、BI、AI 等全技术栈,培养面向未来的数智化人才 (如数据工程师、数据分析师、数据科学家、数据决策者、量化投资人)。
Python
78
72
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
969
572
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
547
76
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
349
1.35 K
giteagitea
喝着茶写代码!最易用的自托管一站式代码托管平台,包含Git托管,代码审查,团队协作,软件包和CI/CD。
Go
17
0
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
205
284
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
60
17