如何使用toZod实现带字段重映射的Zod Schema类型校验?
解决Zod Transform后类型与toZod冲突的问题
问题根源在于:toZod<Country>对应的是ZodObject类型,但调用.transform()方法后,返回的是ZodEffects类型,二者类型不兼容,直接赋值会触发类型错误。
下面提供两种可行的解决方式:
方式一:移除变量类型注解,让Zod自动推导
直接去掉testZodObj的toZod<Country>注解,利用Zod自身的类型推导能力,同时用satisfies确保transform的返回值符合Country接口结构:
import { z } from "zod"; import type { toZod } from "zod-to-ts"; interface Country { isoCode: string; nameEn: string; nameDe: string; phone: string; bla: string; } const CountryJson = { isoCode: "DE", nameEn: "Germany", nameDe: "Deutschland", phone: "+49", blubb: "test123", }; // 移除toZod<Country>注解,让Zod处理类型推导 const testZodObj = z .object({ isoCode: z.string(), nameEn: z.string(), nameDe: z.string(), phone: z.string(), blubb: z.string(), }) .transform((item) => { const { blubb: bla, ...rest } = item; // 用satisfies确保返回值符合Country接口 return { ...rest, bla, } satisfies Country; }); // 可以直接用Country作为返回类型,或通过z.infer推导 function print(): Country { return testZodObj.parse(CountryJson); } const out = print(); console.log(out); // 输出: { isoCode: 'DE', nameEn: 'Germany', nameDe: 'Deutschland', phone: '+49', bla: 'test123' }
方式二:拆分输入输出schema,分别约束类型
如果需要明确约束API输入的结构,可以拆分出API响应和数据库存储两个接口,分别定义对应的Zod schema:
import { z } from "zod"; import type { toZod } from "zod-to-ts"; // 定义API返回的原始结构 interface CountryApiResponse { isoCode: string; nameEn: string; nameDe: string; phone: string; blubb: string; } // 数据库存储的目标结构 interface Country { isoCode: string; nameEn: string; nameDe: string; phone: string; bla: string; } const CountryJson: CountryApiResponse = { isoCode: "DE", nameEn: "Germany", nameDe: "Deutschland", phone: "+49", blubb: "test123", }; // 用toZod约束API输入的schema类型 const countryApiSchema: toZod<CountryApiResponse> = z.object({ isoCode: z.string(), nameEn: z.string(), nameDe: z.string(), phone: z.string(), blubb: z.string(), }); // 基于输入schema做transform,得到数据库目标schema const countryDbSchema = countryApiSchema.transform((item) => { const { blubb: bla, ...rest } = item; return { ...rest, bla, } satisfies Country; }); function print(): Country { return countryDbSchema.parse(CountryJson); } const out = print(); console.log(out);
两种方式都能确保最终返回的类型完全匹配Country接口,同时避免Zod类型冲突。
内容的提问来源于stack exchange,提问作者fuwa07
相关产品推荐
相关产品推荐

