const Person = zod.object({
name: z.string().default(''),
age: z.number().nullable().default(null)
}).default({}); // .default({}) could be omitted in this case but should be set in nested objects
import { z } from "zod";
const schema = z.object({
name: z.string(),
age: z.number().nullable()
});
const schemaDefaults = <Schema extends z.ZodFirstPartySchemaTypes>(
schema: Schema
): z.TypeOf<Schema> => {
switch (schema._def.typeName) {
case z.ZodFirstPartyTypeKind.ZodDefault:
return schema._def.defaultValue();
case z.ZodFirstPartyTypeKind.ZodObject: {
// The switch wasn't able to infer this but the cast should
// be safe.
return Object.fromEntries(
Object.entries(
(schema as z.SomeZodObject).shape
).map(([key, value]) => [key, schemaDefaults(value)])
);
}
case z.ZodFirstPartyTypeKind.ZodString:
return "";
case z.ZodFirstPartyTypeKind.ZodNull:
return null;
case z.ZodFirstPartyTypeKind.ZodNullable:
return null;
// etc
default:
throw new Error(`Unsupported type ${schema._type}`);
}
};
console.log(schemaDefaults(schema));
3条答案
按热度按时间ztmd8pv51#
我知道我参加聚会有点晚了,但也许这会在将来帮助到别人。
您可以通过以下方式扩展
zod
模式:现在,您可以通过调用来检索所需的输出:
pbossiut2#
从库中似乎没有直接的方法来做这类事情,但是您可以深入研究它们的
_
私有字段并获得您正在寻找的功能。这种方法存在一些风险,因为库维护者通常不保证这些私有属性的稳定性。如果您依赖此行为,则可能需要格外小心版本颠簸。
好吧,免责声明,这样的事情是可能的。将其扩展到更多类型留给读者作为练习:
在这里,我没有指定任何默认值,但代码仍然输出您所期望的内容。如果指定“foo”作为
name
的默认值,代码将输出{ name: "foo", age: null }
一种更短的方法是简单地挖掘到模式的
_def
中的一层,寻找要调用的defaultValue
函数,但我认为给定的方法更有原则,因为它可以扩展到支持每个核心zod
模式类型。最后一个警告,有些
zod
类型不像其他类型那样容易处理。像z.number
这样的东西可以合理地默认为0
,但是z.union
或z.intersection
会有有趣的递归情况。可能值得为这种处理构建一个库,或者在repo中打开一个问题,使其成为所提供的API的一部分。
0vvn1miw3#
所以我已经访问过这个线程几次了,现在我想给予我的意见,
因为我的问题是
我想通过利用默认值安全地示例化一个新的zod对象,但也希望我输入所需的非默认值。
所以
.parse
功能只接受unknown
,并不能帮助我理解 * 什么 * 我需要指定什么以及什么是默认值。现在,如果你有同样的问题,你想要像
MyZodObject.createInstance
这样的东西,那么我可能有一个简单的解决方案解决方案为
z.input<typeof MyShape>
这是做什么,它返回你的typescript类型,预计将有所有必要的(必需的)关键字和标记的其余部分,这将是由
.default
作为可选填写。假设你有
一个泛型的Type-Safe方法,用默认值示例化Zod Object