首页
/ 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的类型安全优势,又提供了良好的开发者体验。

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

项目优选

收起
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
184
266
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
138
189
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
887
528
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
370
383
Git4ResearchGit4Research
Git4Research旨在构建一个开放、包容、协作的研究社区,让更多人能够参与到科学研究中,共同推动知识的进步。
HTML
19
0
kernelkernel
deepin linux kernel
C
22
6
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
337
1.11 K
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.08 K
0
note-gennote-gen
一款跨平台的 Markdown AI 笔记软件,致力于使用 AI 建立记录和写作的桥梁。
TSX
84
4
harmony-utilsharmony-utils
harmony-utils 一款功能丰富且极易上手的HarmonyOS工具库,借助众多实用工具类,致力于助力开发者迅速构建鸿蒙应用。其封装的工具涵盖了APP、设备、屏幕、授权、通知、线程间通信、弹框、吐司、生物认证、用户首选项、拍照、相册、扫码、文件、日志,异常捕获、字符、字符串、数字、集合、日期、随机、base64、加密、解密、JSON等一系列的功能和操作,能够满足各种不同的开发需求。
ArkTS
61
2