-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
z.coerce.object()
should be a thing
#2786
Comments
This helper function is doing what I want: /** zod schema to force the value into an object, if it isn't already. */
function coerceObject<T extends z.ZodRawShape>(shape: T) {
return z.object({}).passthrough().catch({}).pipe(z.object(shape));
} Now instead of Resulting in this behavior: const configurationSchema = coerceObject({
chats: coerceObject({
max_characters: z.number().catch(5000),
max_media_attachments: z.number().catch(1),
}),
groups: coerceObject({
max_characters_description: z.number().catch(160),
max_characters_name: z.number().catch(50),
}),
media_attachments: coerceObject({
image_matrix_limit: z.number().optional().catch(undefined),
image_size_limit: z.number().optional().catch(undefined),
supported_mime_types: mimeSchema.array().optional().catch(undefined),
video_duration_limit: z.number().optional().catch(undefined),
video_frame_rate_limit: z.number().optional().catch(undefined),
video_matrix_limit: z.number().optional().catch(undefined),
video_size_limit: z.number().optional().catch(undefined),
}),
polls: coerceObject({
max_characters_per_option: z.number().catch(25),
max_expiration: z.number().catch(2629746),
max_options: z.number().catch(4),
min_expiration: z.number().catch(300),
}),
statuses: coerceObject({
max_characters: z.number().catch(500),
max_media_attachments: z.number().catch(4),
}),
});
configurationSchema.parse({}) // { chats: { max_characters: 5000, ... }, ... } What do you think @colinhacks, should this belong in the main library? It was one of my biggest issues with zod until I learned how to get good at it. It's especially useful when you have deeply-nested data and you cannot guarantee certain deep values exist. Some APIs really do this! Eg: https://mastodon.social/api/v1/instance Between different Mastodon servers I have no clue what fields will be available. |
@alexgleason, I think the helper below should work the same as yours; the one benefit is a narrower return type that works with function coerceObject<T extends z.ZodRawShape>(
shape: T,
params?: z.RawCreateParams,
) {
return new z.ZodEffects({
schema: z.object(shape, params),
effect: { type: "preprocess", transform: Object },
typeName: z.ZodFirstPartyTypeKind.ZodEffects,
});
} This is basically Here it is with an explicit function return type: function coerceObject<T extends z.ZodRawShape>(
shape: T,
params?: z.RawCreateParams,
): z.ZodEffects<
z.ZodObject<
T,
"strip",
z.ZodTypeAny,
z.objectOutputType<T, z.ZodTypeAny, "strip">,
z.objectInputType<T, z.ZodTypeAny, "strip">
>,
z.objectOutputType<T, z.ZodTypeAny, "strip">,
z.objectInputType<T, z.ZodTypeAny, "strip">
> {
return new z.ZodEffects({
schema: z.object(shape, params),
effect: { type: "preprocess", transform: Object },
typeName: z.ZodFirstPartyTypeKind.ZodEffects,
});
} Unfortunately it still doesn't return a |
Instead of:
We should be able to:
z.coerce.object
would be roughly equivalent to:All keys of the shape need to be a
ZodCatch
orZodOptional
, otherwise it's a TypeError.The text was updated successfully, but these errors were encountered: