使用toZod处理TRPC推断类型时出现strip错误
问题背景
toZod是用来生成和TypeScript类型匹配的Zod Schema的工具,能提供属性自动提示,类型变更时还会报错提醒。之前在普通TS类型上用得没问题,但现在把它用在TRPC的inferRouterOutputs推断出的类型上时,出现了和"strip"相关的类型错误,而且按Ctrl+Space也弹不出属性提示。
代码示例:
type RouterOutput = inferRouterOutputs<AppRouter>; type DefinitionTree = RouterOutput["product"]["getProductDefinitionTree"]; const treeSchema: toZod<DefinitionTree> = z.object({ // 这里本该弹出属性提示,但没有 }).array();
错误详情
鼠标悬停在treeSchema上时,显示的类型错误:
Type 'ZodArray<ZodObject<{}, "strip", ZodTypeAny, {}, {}>, "many">' is not assignable to type 'ZodArray<ZodObject<{ product: ZodNullable<ZodObject<{ id: ZodString; name: ZodNullable
; description: ZodNullable ; createdById: ZodNullable ; ... 4 more ...; updatedAt: ZodNullable<...>; }, "strip", ZodTypeAny, Product, Product>>; ... 31 more ...; competitorReference: ZodNullable<...> ...'.
Type 'ZodObject<{}, "strip", ZodTypeAny, {}, {}>' is not assignable to type 'ZodObject<{ product: ZodNullable<ZodObject<{ id: ZodString; name: ZodNullable
; description: ZodNullable ; createdById: ZodNullable ; ... 4 more ...; updatedAt: ZodNullable<...>; }, "strip", ZodTypeAny, Product, Product>>; ... 31 more ...; competitorReference: ZodNullable<...> | ZodNull...'.
Type '{}' is missing the following properties from type '{ product: ZodNullable<ZodObject<{ id: ZodString; name: ZodNullable
; description: ZodNullable ; createdById: ZodNullable ; ... 4 more ...; updatedAt: ZodNullable<...>; }, "strip", ZodTypeAny, Product, Product>>; ... 31 more ...; competitorReference: ZodNullable<...> | ZodNullable<...>; }': product, supplierData, models, existingDrawings, and 29 more.
解决方案
先提取纯TS类型,剥离Zod内部标记
TRPC的inferRouterOutputs返回的类型可能嵌套了Zod的内部结构(比如带"strip"修饰的ZodObject),toZod无法直接识别。可以换一种方式提取纯TS类型:// 从路由函数的返回值推导纯TS类型 type DefinitionTree = Awaited<ReturnType<typeof AppRouter.product.getProductDefinitionTree>>;或者直接从TRPC路由的Zod Schema反向推导:
type DefinitionTree = z.infer<typeof AppRouter.product.getProductDefinitionTree._def.outputType>;不要直接断言toZod类型,让工具自动推导
别给变量直接指定toZod<DefinitionTree>类型,先定义完整的Zod Schema,再验证是否匹配目标类型:const treeSchema = z.object({ product: z.object({ id: z.string(), name: z.string().nullable(), description: z.string().nullable(), // 补全其他product属性 }).nullable(), supplierData: z.object({/* 对应类型的Schema */}), // 补全剩余31个属性 }).array(); // 验证Schema是否匹配目标类型,不匹配会直接报错 type CheckMatch = z.infer<typeof treeSchema> extends DefinitionTree ? true : false;手动对齐ZodObject的"strip"模式
如果toZod对"strip"模式支持不完善,可以手动给z.object指定该模式,和目标类型的结构对齐:const treeSchema: toZod<DefinitionTree> = z.object({ // 填充所有必要属性 }, { strip: true }).array();升级toZod版本
部分版本的toZod对嵌套的Zod类型支持不足,尝试升级到最新版,可能已经修复了这类兼容性问题。
内容的提问来源于stack exchange,提问作者tdev

