如何获取Zod中转换后数组的元素Schema?
解决方案
你遇到的问题是因为transform返回的是ZodEffects类型的Schema,而非ZodArray,所以没有.element属性。以下是两种简便的解决方式:
方法一:提前定义前端元素Schema,通过pipe约束转换结果
先定义前端需要的元素结构Schema,再用pipe将转换后的结果与该数组Schema绑定,这样最终的Schema就具备ZodArray的所有属性(包括.element):
const oZodBackendData = z .object({ results: z.array( z.object({ attr: z.string(), }) ), }) .readonly(); // 定义前端元素的Schema const zFrontendItem = z.object({ otherName: z.string() }).readonly(); // 定义前端数组Schema const zFrontendData = z.array(zFrontendItem).readonly(); export const oZodData = oZodBackendData .transform((oBackendData) => oBackendData.results.map((oBackendDataElement) => ({ otherName: oBackendDataElement.attr, })) ) .pipe(zFrontendData) // 用pipe将转换结果约束为数组Schema .readonly(); export type Data = z.infer<typeof oZodData>; // 现在可以正常访问element了 oZodData.element; // 类型为typeof zFrontendItem
方法二:从推断的类型反向推导元素Schema(适用于不想提前定义的场景)
如果不想提前定义元素Schema,可以先从转换后的数组类型中提取元素类型,再用z.inferSchema(Zod v3.22.0+支持)生成对应的Schema:
const oZodBackendData = z .object({ results: z.array( z.object({ attr: z.string(), }) ), }) .readonly(); export const oZodData = oZodBackendData .transform((oBackendData) => oBackendData.results.map((oBackendDataElement) => ({ otherName: oBackendDataElement.attr, })) ) .readonly(); export type Data = z.infer<typeof oZodData>; // 提取数组元素类型 export type DataItem = Data[number]; // 从类型反向生成Schema const zDataItem = z.inferSchema<DataItem>();
注意:方法二只能获取元素的Schema,若要让oZodData本身拥有.element属性,方法一更直接且更符合Zod的类型约束逻辑。
内容的提问来源于stack exchange,提问作者szelbi
相关产品推荐
相关产品推荐

