oRPC:把 OpenAPI 请求的 JSON 类型错误挡在门外
该项目围绕「Typesafe APIs Made Simple. @orpc/json-schema: Smart coercion for OpenAPI requests.」构建,适用于实际场景的开源实践,提供可复用的工具链与集成方式。
秒懂
- 它是什么?
- oRPC 是一套 TypeScript 优先的 API 开发工具,核心是契约驱动和端到端类型安全。本文聚焦 @orpc/json-schema 的智能强制转换,以及它在实际工程中的边界。
- 适合谁用?
- oRPC 适合已经重度使用 TypeScript、并且愿意把 API 契约作为单一事实来源的团队。它不适合那些需要完全动态类型、或者不想引入额外抽象层的项目。
- 能商用吗?
- 可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
- 还在维护吗?
- 在维护。仓库最近一次提交在 1 天前。
- 用什么语言写的?
- 主要是 TypeScript(依据 GitHub 的语言统计)。
以上回答依据项目的 GitHub 数据(最近同步于 2026年9月14日)和我们的分析,不构成法律意见。
开源项目深度解析
它解决的是 API 类型断裂问题
前后端各写一套类型定义,接口一改就崩,这是很多 TypeScript 项目的常态。oRPC 想用契约文件把类型统一起来。@orpc/contract 定义 API 契约,作为唯一事实来源。服务端用 @orpc/server 实现契约,客户端用 @orpc/client 消费,类型在编译期就能对齐。它面向的是已经用 TypeScript 写全栈、但被手写类型和运行时校验割裂困扰的团队。不是给纯 JavaScript 项目用的,也不是给那些喜欢自由定义接口的人用的。
契约先行的数据流
工作流程分三段。先用 @orpc/contract 写一个 contract,声明输入输出类型,可以配合 Zod 或 Valibot 做校验。然后服务端用 @orpc/server 实现这个 contract,过程类似写一个普通函数。客户端用 @orpc/client 调用,拿到的是完全推断出的类型。@orpc/openapi 负责生成 OpenAPI 文档,让非 oRPC 的客户端也能调用。整个过程里,类型定义只写一次,其余都是推导。README 里明确说 contract 是 single source of truth,这决定了它的架构重心。
@orpc/json-schema 的强制转换机制
OpenAPI 请求通常来自 HTTP,query 参数和路径参数都是字符串,但契约里可能是数字或布尔值。@orpc/json-schema 做的就是智能强制转换,把字符串转成目标类型。这不是简单的 String() 或 Number(),而是基于 JSON Schema 的类型信息来做。例如一个 schema 声明为 integer,请求里来的是 "42",它就会转成 42。布尔值类似,"true" 转成 true。这个包独立于核心流程,意味着你可以只用它处理 OpenAPI 兼容层的输入。但文档没有列出具体支持哪些格式,比如日期字符串或枚举值,需要看源码确认。
跑起来需要哪些步骤
安装时按需取包。核心是 @orpc/contract、@orpc/server、@orpc/client。如果你用 Zod,就加 @orpc/zod。一个最小例子:用 @orpc/contract 定义 contract,用 @orpc/zod 写一个 zod schema 作为输入,然后 @orpc/server 里实现它。客户端创建用 @orpc/client,直接调用方法。具体命令 README 没有给,但 npm 安装是 npm install @orpc/contract @orpc/server @orpc/client。配置项也依赖你选的框架,比如 Next.js 用 @orpc/next,NestJS 用 @orpc/nest。想生成 OpenAPI 就装 @orpc/openapi,它会根据契约自动生成文档。
它不适合的场景
强制转换有代价。如果客户端传了一个无法转换的值,比如字符串 "abc" 给数字字段,转换会失败,错误处理变得关键。文档没有说明失败时的具体行为,是抛异常还是返回 400,需要你自己测试。另外,oRPC 的契约是静态的,如果你需要根据请求动态改变响应结构,这套模型会很别扭。还有,它依赖 TypeScript 的编译期检查,如果项目里有大量 any 或者用 JavaScript 写,类型安全就形同虚设。最后,beta 版本意味着 API 可能变动,生产环境要用得谨慎。
和 tRPC 的差异
tRPC 是另一个流行的 TypeScript RPC 方案,oRPC 明确提供了 @orpc/trpc 来复用现有 tRPC 路由器。两者思路不同:tRPC 更偏向 server functions 的直接调用,类型从服务端函数推导,但 OpenAPI 兼容性弱。oRPC 把契约独立出来,先定义 contract 再实现,这让你可以更容易生成 OpenAPI 文档,也方便多客户端。如果你已经有 tRPC 路由,oRPC 允许你保留它们,通过适配器接入。选择取决于你更看重 RPC 的简便,还是 OpenAPI 的标准化。
维护和升级成本
项目处于 v2.0.0-beta 阶段,最近三周内连续发了 beta.29、beta.30、beta.31,说明迭代很快。升级频率高,意味着你要频繁跟进。每个包独立版本,但核心包之间可能有兼容性要求。许可证是 MIT,可以商用,但没有法律建议,具体条款自己看。文档站是 orpc.dev,README 里没有详细教程,学习成本主要在理解契约模式。如果你只用 @orpc/json-schema,需要单独验证它的版本依赖,因为它是独立包。
编辑结论
oRPC 适合已经重度使用 TypeScript、并且愿意把 API 契约作为单一事实来源的团队。它不适合那些需要完全动态类型、或者不想引入额外抽象层的项目。如果你决定采用,先验证 @orpc/json-schema 的强制转换规则是否覆盖你的字段类型,尤其是数字和布尔值的边界情况。还要确认你使用的运行时(Node、Bun、Cloudflare)有对应的适配器,因为 README 中列出的适配器并不保证每个都稳定。最后,检查当前版本是 v2.0.0-beta.31,beta 阶段的 API 可能变动,升级前要读变更日志。
社区笔记