There's no ergonomic way to rename object properties or do .partial() etc on object transformation pipelines
#2805
-
|
Consider the case where you want to build an API response with camelCase properties in JS, and then send it over the wire with snake_case properties: const Post =
z.object({
id: z.string(),
body: z.string(),
userId: z.string(),
})
.transform(
({ userId, ...rest }) => ({ ...rest, user_id: userId })
)
.pipe(z.object({
id: z.string(),
body: z.string(),
user_id: z.string(),
}))You might want to do const PostSelection = Post.partial() // plz?One could create the following helper function for this. But this all feels very cumbersome. Maybe in an alternate universe, Zod has a more ergonomic way to do all of this? function pipelinePartial(schema) {
if (schema instanceof z.ZodObject) {
return schema.partial()
}
if (schema instanceof z.ZodPipeline) {
return z.pipeline(pipelinePartial(schema._def.in), pipelinePartial(schema._def.out))
}
if (schema instanceof z.ZodEffects) {
return z.effects(pipelinePartial(schema._def.schema), schema._def.effect)
}
throw new Error(`unsupported schema type: ${schema.constructor.name}`)
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
|
Is this what you are looking for? import { z } from 'zod'
import _ from 'lodash'
const snakeCaseKeys = ( data: object ) => _.mapKeys( data, ( val, key ) => _.snakeCase( key ) )
const Post = z.object( {
id: z.string(),
body: z.string(),
userId: z.string(),
} )
console.log(
Post.parse( {
id: '1',
body: 'body',
userId: '1',
} )
)
// {
// id: "1",
// body: "body",
// userId: "1"
// }
const snakeCasedPost = Post.transform( snakeCaseKeys )
console.log(
snakeCasedPost.parse( {
id: '1',
body: 'body',
userId: '1',
} )
)
// {
// id: "1",
// body: "body",
// user_id: "1"
// }
const snakeCasedPartialPost = Post.partial().transform( snakeCaseKeys )
console.log(
snakeCasedPartialPost.parse( {
userId: '1',
} )
)
// {
// user_id: "1"
// }If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏 |
Beta Was this translation helpful? Give feedback.
-
|
Whilst this meets the user's need, it doesn't really qualify as ergonomic (or first-class) solution. I think we should consider something like: const post = z.object({
id: z.string(),
body: z.string(),
first_name: z.string().rename('firstName'),
});
post.parse({ id: 1, body: 'Hello World', first_name: 'Giuseppe' });
// { id: 1, body: 'Hello World', firstName: 'Giuseppe' } |
Beta Was this translation helpful? Give feedback.
Is this what you are looking for?