Use Zod schema after parse & transform as a new schema

I am looking how I could handle from validation with one schema so it can be used on the ReactHookForm zod resolver and tRPC input validation. lets say my form accepts two values
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})

type SchemaT = z.infer<typeof asd>

const asdzz: SchemaT = {
bir: 'asd',name: 'as'
}
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})

type SchemaT = z.infer<typeof asd>

const asdzz: SchemaT = {
bir: 'asd',name: 'as'
}
schema is a parser for client form input which I would like to use resulting type of that schema as a new schema for tRPC input validation. Can I do this somehow? Or my bet is just don't do the transform and use that schema both on client and backend and on backend extract needed fields and do further processing. This will be simpler but unnecessary bloat of data payload would be then sent to the server
4 Replies
Jacob
Jacob3mo ago
So just going to add a clarifying question, you are using the schema:
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})
for the client side form validation? and for example you would want the tRPC validation schema to look something like this?:
const schema = z.object({
name: z.string(),
bir: z.string()
})
const schema = z.object({
name: z.string(),
bir: z.string()
})
Is that correct or do i have it wrong?
Mugetsu
MugetsuOP3mo ago
@Jacob yes, exactly.
Jacob
Jacob3mo ago
@Mugetsu So what i would recommend is the following:
// your default schema
const clientSchema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),
})

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.extend({
bir: z.string(), // overriding the bir field and keeping all other fields
})
// your default schema
const clientSchema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),
})

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.extend({
bir: z.string(), // overriding the bir field and keeping all other fields
})
What you could also do, is lets say we have many client fields that aren't all needed on the server e.g:
// your default schema
const clientSchema = z.object({
uid: z.string().uuid(),
name: z.string(),
bir: z
.object({
value: z.string(),
label: z.string(),
})
.transform((val) => val.value),
});

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.omit({ uid: true }).extend({
bir: z.string(), // overriding the bir field and keeping all other fields
});
// your default schema
const clientSchema = z.object({
uid: z.string().uuid(),
name: z.string(),
bir: z
.object({
value: z.string(),
label: z.string(),
})
.transform((val) => val.value),
});

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.omit({ uid: true }).extend({
bir: z.string(), // overriding the bir field and keeping all other fields
});
Or instead of omitting the value you could use the .pick method:
// your default schema
const clientSchema = z.object({
uid: z.string().uuid(),
name: z.string(),
bir: z
.object({
value: z.string(),
label: z.string(),
})
.transform((val) => val.value),
});

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.pick({ name: true, bir: true }).extend({
bir: z.string(), // overriding the bir field and keeping all other fields
});
// your default schema
const clientSchema = z.object({
uid: z.string().uuid(),
name: z.string(),
bir: z
.object({
value: z.string(),
label: z.string(),
})
.transform((val) => val.value),
});

// your server schema which will extend the clientSchema
const serverSchema = clientSchema.pick({ name: true, bir: true }).extend({
bir: z.string(), // overriding the bir field and keeping all other fields
});
Note: When using the .extend method even if you remove the field on the clientSchema it will still be there on the serverSchema
Mugetsu
MugetsuOP2mo ago
Thanks @Jacob it helped me a lot with ur suggestions!
Want results from more Discord servers?
Add your server