如何在TypeScript中正确使用经Zod序列化后的对象类型?
解决Zod Transform导致TypeScript类型不匹配的问题
你遇到的核心问题是:Zod的transform(JSON.stringify)把booking字段的类型从预订项数组转换成了字符串,但你的build函数仍试图以原始数组元素的方式访问type属性,自然触发类型错误。以下是几种无需关闭类型检查的解决方案:
方案1:拆分Schema,区分原始类型与序列化后类型
把原始预订项的Schema单独提取,既保留业务处理所需的原始类型,又能得到序列化后的最终类型:
// 定义原始预订项的Schema与类型 const BookingItem = z.discriminatedUnion('type', [ z.object({ type: z.literal('url'), input: z.string().url() }), z.object({ type: z.literal('email'), input: z.string().email() }) ]); type BookingItem = z.infer<typeof BookingItem>; type BookingArray = BookingItem[]; // 定义最终的Event Schema,对booking做序列化转换 export const Event = z.object({ // 其他字段... booking: z.array(BookingItem).transform(t => JSON.stringify(t)) }); export type Event = z.infer<typeof Event>;
修改build函数,让它接收原始的BookingArray类型:
export const build = (booking: BookingArray) => { const output: string[] = []; for (const b of booking) { if (b.type === 'url') output.push(`abc`); if (b.type === 'email') output.push(`xyz`); } return output; };
方案2:若必须处理序列化后的字符串(不推荐)
如果build函数只能拿到已序列化的字符串(比如从后端返回的数据),需先解析回原始数组,并用Zod验证保证类型安全:
export const build = (bookingStrings: Event['booking'][]) => { const output: string[] = []; for (const str of bookingStrings) { // 用Zod解析并验证字符串转数组的结果 const bookingItems = z.array(BookingItem).parse(JSON.parse(str)); for (const b of bookingItems) { if (b.type === 'url') output.push(`abc`); if (b.type === 'email') output.push(`xyz`); } } return output; };
方案3:调整序列化时机(业务允许时优先选)
如果不需要在Schema层面完成序列化,可把转换逻辑移到业务代码中,让Schema保留原始数组类型:
export const Event = z.object({ // 其他字段... booking: z.array( z.discriminatedUnion('type', [ z.object({ type: z.literal('url'), input: z.string().url() }), z.object({ type: z.literal('email'), input: z.string().email() }) ]) ) }); export type Event = z.infer<typeof Event>; // 在需要序列化的场景手动转换 const parsedEvent = Event.parse(rawData); const serializedBooking = JSON.stringify(parsedEvent.booking);
此时build函数直接使用Event['booking']类型即可正常访问type属性。
内容的提问来源于stack exchange,提问作者charnould
相关产品推荐
相关产品推荐

