Recursively remove schema defaults #845
-
Hello, I'm seeking a means of recursively discarding schema defaults. Something akin to
Any bright ideas? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 10 replies
-
You probably have a good reason for not doing this, but is there any reason not to define the base schema as not containing the defaults and then extend that schema with defaults? I know that isn't the DRY-est solution, but there isn't anything built into zod to do this, and I imagine doing it as a generic function will be tricky to get the return type inference to be correct. |
Beta Was this translation helpful? Give feedback.
-
oof, the rabbit hole just keeps getting deeper. After looking into it more, making function deepRemoveDefaults ( schema: z.ZodTypeAny ): any {
if ( schema instanceof z.ZodDefault )
return deepRemoveDefaults( schema.removeDefault() )
if ( schema instanceof z.ZodObject ) {
const newShape: any = {}
for ( const key in schema.shape ) {
const fieldSchema = schema.shape[ key ]
newShape[ key ] = z.ZodOptional.create( deepRemoveDefaults( fieldSchema ) )
}
return new z.ZodObject( {
...schema._def,
shape: () => newShape,
} ) as any
}
if ( schema instanceof z.ZodArray )
return z.ZodArray.create( deepRemoveDefaults( schema.element ) )
if ( schema instanceof z.ZodOptional )
return z.ZodOptional.create( deepRemoveDefaults( schema.unwrap() ) )
if ( schema instanceof z.ZodNullable )
return z.ZodNullable.create( deepRemoveDefaults( schema.unwrap() ) )
if ( schema instanceof z.ZodTuple )
return z.ZodTuple.create( schema.items.map( ( item: any ) => deepRemoveDefaults( item ) ) )
return schema
} const schema = z.object( {
string: z.string().default( 'default' ),
number: z.number().default( 42 ),
object: z.object( {
nestedString: z.string().default( 'default' ),
} ).default( {} ),
} ).default( {} )
const schemaNoDefaults = deepRemoveDefaults( schema )
const schemaTestObj: z.infer<typeof schema> = { string: 'foo', number: 123, object: { nestedString: 'bar' } }
console.log( schema.safeParse( schemaTestObj ) ) // { success: true, data: { string: 'foo', number: 123, object: { nestedString: 'bar' } } }
console.log( schema.safeParse( undefined ) ) // { success: true, data: { string: 'default', number: 42, object: { nestedString: 'default' } } }
console.log( schemaNoDefaults.safeParse( schemaTestObj ) ) // { success: true, data: { string: 'foo', number: 123, object: { nestedString: 'bar' } } }
console.log( schemaNoDefaults.safeParse( {} ) ) // { success: true, data: {} } |
Beta Was this translation helpful? Give feedback.
-
@sosweetham @traversable/zod supports this. I put together a demo, lmk if you run into any issues. |
Beta Was this translation helpful? Give feedback.
oof, the rabbit hole just keeps getting deeper.
After looking into it more, making
deepRemoveDefaults
wasn't too complicated. So it could be a cool idea for Zod to add, but until they do, here is a function that should work. I haven't done a ton of testing on this, so you may need to make a few tweeks. I just copieddeepPartialify
and made a few changes. Hope this solves your problem.