| name | zod-patterns |
| description | MX Space project Zod schema patterns. Apply when creating DTOs, validation schemas, or handling request validation. |
| user-invocable | false |
Zod Schema Patterns
Basic Pattern
import { z } from 'zod'
import { createZodDto } from 'nestjs-zod'
export const MySchema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive().optional(),
})
export class MyDto extends createZodDto(MySchema) {}
export class PartialMyDto extends createZodDto(MySchema.partial()) {}
Project Custom Validators
Location: apps/core/src/common/zod/
import {
zNonEmptyString,
zCoerceInt,
zCoercePositiveInt,
zCoerceBoolean,
zCoerceDate,
zOptionalDate,
zOptionalBoolean,
zEmptyStringToNull,
zNilOrString,
zHexColor,
zAllowedUrl,
zStrictUrl,
zHttpsUrl,
zPaginationPage,
zPaginationSize,
zSortOrder,
zArrayUnique,
zUniqueStringArray,
zBooleanOrString,
zTransformEmptyNull,
zTransformBoolean,
zPinDate,
zSlug,
zEmail,
zUrl,
zMaxLengthString,
zRefTypeTransform,
zPrefer,
zLang,
zEntityId,
zEntityIdOrInt,
} from '~/common/zod'
Entity ID Validation
import { zEntityId } from '~/common/zod'
const Schema = z.object({
id: zEntityId,
categoryId: zEntityId,
relatedIds: z.array(zEntityId),
})
import { EntityIdDto } from '~/shared/dto/id.dto'
Extending Base Schemas
const PostSchema = z.object({
title: zNonEmptyString,
slug: zSlug,
categoryId: zEntityId,
tags: z.array(z.string()).optional(),
contentFormat: z.enum(['markdown', 'lexical']),
})
Common Patterns
Optional Fields with Defaults
z.boolean().default(true).optional()
z.number().default(0).optional()
z.array(z.string()).default([]).optional()
Preprocessing
z.preprocess(
(val) => (val === '' ? null : val),
z.string().nullable()
).optional()
z.preprocess(
(val) => (typeof val === 'string' ? parseInt(val, 10) : val),
z.number()
)
Union Types
z.union([z.string(), z.number()])
z.enum(['draft', 'published', 'archived'])
Array Validation
z.array(z.string())
z.array(z.string()).min(1).max(10)
zArrayUnique(z.string())
Nested Objects
const AddressSchema = z.object({
street: z.string(),
city: z.string(),
})
const UserSchema = z.object({
name: z.string(),
address: AddressSchema.optional(),
addresses: z.array(AddressSchema).optional(),
})
Conditional Validation
z.object({
password: z.string(),
confirmPassword: z.string(),
}).refine(
(data) => data.password === data.confirmPassword,
{ message: 'Passwords must match' }
)
Type Inference
type MyType = z.infer<typeof MySchema>
async create(data: z.infer<typeof MySchema>) {
return this.repository.create(data)
}