Here is my example code
import { z, ZodTypeAny, ZodObject } from 'zod';
function deepShapeLog(schemanName: string, schema: ZodTypeAny, indent = 0) {
const indentStr = ' '.repeat(indent);
console.log(`${indentStr}${schemanName} : ${schema._def.typeName}`);
if (schema instanceof ZodObject) {
for (const key in schema.shape) {
deepShapeLog(key, schema.shape[key], indent + 4);
}
}
}
const deepObj1 = z.object({
obj1: z.object({
obj2: z.object({
obj3: z.object({
field4: z.string(),
field5: z.string()
}),
field6: z.number(),
}),
field7: z.boolean()
}),
field8: z.date(),
})
deepShapeLog('deepObj1', deepObj1);
const deepObj1Partial = deepObj1.deepPartial();
deepShapeLog('\ndeepObj1Partial', deepObj1Partial);
/* output from node v20.8.0 and zod 3.22.4
deepObj1 : ZodObject
obj1 : ZodObject
obj2 : ZodObject
obj3 : ZodObject
field4 : ZodString
field5 : ZodString
field6 : ZodNumber
field7 : ZodBoolean
field8 : ZodDate
deepObj1Partial : ZodObject
obj1 : ZodOptional
field8 : ZodOptional
*/
And I want to take an exact copy of the structure with all fields and nested objects set to optional.
I've tried ZodObject.deepPartial, however, this lost the fields in my nested objects.
I've tried creating a recursive function, however, it seems that the copy constructor of the ZodObject loses the fields of nested objects, so as the recursion unfolds the sub-collections are lost.
I've spent 8 hours on this (i'm ashamed to say), I've even tried writing a nun recursive function... I just don't understand why this would be so hard, I'm clearly missing something.
The weird thing is that the vs code type script compiler thinks everything is fine and gives me the following hint: vs code hint of deepObjPartial
however at run time all the sub shape is gone...
writing some example code really helped me understand a principle of zod that had just past me by.
I had thought that optionality was just an attribute of the field, however it turns out (and I'm sure for good reason) that it actually wraps the object in an optional type... and you need to unwrap it to access the actual feild... just like the docs say.
here is an updated deepShapeLog and same example above:
As I said in the post, I was clearly missing something... now I know what it is! Can't believe it took me more than 8 hours to work that out though... :-/
hopefully this will save someone else those 8 hours...