FEATURED · 精选文章

如何用 tRPC errorFormatter 把 Zod 校验错误以类型安全方式传给客户端展示

发布时间 / 2026/9/11 1:40:04
来源 / 创域科博编辑部
栏目 / 资讯中心
如何用 tRPC errorFormatter 把 Zod 校验错误以类型安全方式传给客户端展示 如何用 tRPC errorFormatter 把 Zod 校验错误以类型安全方式传给客户端展示【免费下载链接】trpc‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.项目地址: https://gitcode.com/GitHub_Trending/tr/trpc假设你的 tRPC API 用 Zod 校验了 procedure 的入参。当客户端提交了非法输入时默认响应里只有一句password must be at least 4 characters这样的通用 message拿不到“哪个字段、什么错误”的结构化信息也就没法在表单里逐条渲染。本文的目标就是在服务端用initTRPC的errorFormatter把ZodError的flatten()结果放进错误对象的data里并让这份结构一路推导infer到 React 客户端使mutation.error.data.zodError在编辑器里是具体类型而不是unknown从而可以直接读取字段并展示。整条路径依据 error formatting 文档给出的服务端errorFormatter与 React 用法示例入参与依赖安装分别参考 validators 和 React 集成 setup。前提条件按 React 集成 setup 的说明这套 React 集成需要安装以下依赖trpc/react-query依赖tanstack/react-querynpm install trpc/server trpc/client trpc/react-query tanstack/react-query此外服务端示例用到了zod因为示例中的入参校验基于 Zod。服务端示例里用到了initTRPC、ZodError、z分别来自trpc/server和zod。服务端在 initTRPC.create 里挂 errorFormattererrorFormatter在initTRPC.create()里配置。文档说明router 里的错误格式会一路推导到客户端The error formatting in your router will be inferred all the way to your client这正是类型安全的关键——你在服务端返回的data结构决定了客户端能读到什么类型。下面这段是 error formatting 文档中 React 示例所给出的完整服务端代码server.tsimport { initTRPC } from trpc/server; import { ZodError } from zod; import { z } from zod; const t initTRPC.create({ errorFormatter(opts) { const { shape, error } opts; return { ...shape, data: { ...shape.data, zodError: error.code BAD_REQUEST error.cause instanceof ZodError ? error.cause.flatten() : null, }, }; }, }); export const appRouter t.router({ addPost: t.procedure.input(z.object({ title: z.string() })).mutation(({ input }) input), }); export type AppRouter typeof appRouter;几个需要理解的点都来自 error formatting 文档errorFormatter(opts)收到的opts包含error、type、path、input、ctx、shape其中shape是{ message: string; code: number; data: unknown }。error.cause instanceof ZodError配合error.code BAD_REQUEST用来识别“这是入参校验失败”。只有命中该条件时才填充zodError否则为null。这里用...shape.data保留了默认错误数据的字段。默认的DefaultErrorData含code、httpStatus、path?以及仅开发环境出现的stack?。也就是说errorFormatter是在默认错误结构之上追加zodError字段而不是替换整个响应。默认错误结构可以对照 error handling 文档给出的入参错误示例code为-32600、data.code为BAD_REQUEST、data.httpStatus为400。客户端创建 hooks 并读取推导出来的错误在客户端用一个文件导出createTRPCReactAppRouter()创建的trpc对象它从服务端的AppRouter类型推导出所有 hook来自文档中的utils/trpc.tsximport { createTRPCReact } from trpc/react-query; import type { AppRouter } from ../server; export const trpc createTRPCReactAppRouter();然后在组件里用useMutation触发那个带 Zod 输入的 procedure并读取mutation.error.data.zodError。下面是文档中components/MyComponent.tsx的用法import { useEffect } from react; import { trpc } from ../utils/trpc; export function MyComponent() { const mutation trpc.addPost.useMutation(); useEffect(() { mutation.mutate({ title: example }); }, []); if (mutation.error?.data?.zodError) { // zodError will be inferred return ( preError: {JSON.stringify(mutation.error.data.zodError, null, 2)}/pre ); } return [...]/; }说明useEffect里的mutation.mutate(...)是文档用来触发一次调用、从而走到错误分支的写法实际项目里通常由用户操作触发 mutation。末尾的[...]/是文档里“组件其余 UI”的占位写法替换成你组件正常的返回内容即可。关键在if (mutation.error?.data?.zodError)由于服务端errorFormatter的返回结构被推导到了客户端mutation.error.data.zodError在这里是ZodError.flatten()的结构类型而不是unknown因此可以直接按字段读取并展示。结果验证文档给出的判断方式有两层类型层面——文档明确注释 “zodError will be inferred”即mutation.error.data.zodError由服务端errorFormatter的返回类型推导而来。在编辑器里悬停或访问其子字段时你会得到flatten()的结构而不是unknown这是“类型安全传给客户端”的直接体现。运行时层面——当入参不满足 Zod schema 时服务端返回BAD_REQUEST且error.cause是ZodErrorif (mutation.error?.data?.zodError)分支命中组件用JSON.stringify(mutation.error.data.zodError, null, 2)渲染出该错误对象。限制与说明errorFormatter的zodError只在error.code BAD_REQUEST error.cause instanceof ZodError时填充否则为null。它针对的是入参校验失败validators 文档指出输出校验失败会以INTERNAL_SERVER_ERROR响应不会被这里的zodError覆盖。默认错误数据中的stack只在开发环境出现error handling 说明initTRPC.create()默认把isDev设为process.env.NODE_ENV ! production需要确定性行为时可手动传isDev。tRPC 兼容 JSON-RPC 2.0shape.code是数字如-32600而data.code是BAD_REQUEST这类TRPC_ERROR_CODE_KEY两者不是同一字段读取时注意区分。更多错误码表与TRPCError、onError的用法见 error handlinginferRouterInputs/inferRouterOutputs等从AppRouter推导类型的手动方式见 Inferring Types。【免费下载链接】trpc‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.项目地址: https://gitcode.com/GitHub_Trending/tr/trpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻