O que é Zod
Zod é uma biblioteca de declaração de schemas e validação TypeScript-first. Apenas definindo um schema, você pode realizar validação e inferência de tipos simultaneamente.
Novas Funcionalidades do Zod 4
Melhorias de Performance
Velocidade de validação:
- Zod 3: 100,000 ops/sec
- Zod 4: 300,000 ops/sec (3x mais rápido)
Velocidade de parsing:
- Até 5x mais rápido em schemas complexos
Nova API de Metadados
import { z } from 'zod';
const userSchema = z.object({
name: z.string().describe('Nome do usuário'),
email: z.string().email().describe('Endereço de email'),
age: z.number().min(0).max(150).describe('Idade')
}).describe('Informações do usuário');
// Obter metadados
const metadata = userSchema.description;
const fields = userSchema.shape;
Uso Básico
Definição de Schema
import { z } from 'zod';
// Tipos primitivos
const stringSchema = z.string();
const numberSchema = z.number();
const booleanSchema = z.boolean();
const dateSchema = z.date();
// Objeto
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
age: z.number().int().positive().optional(),
role: z.enum(['user', 'admin']),
createdAt: z.date().default(() => new Date())
});
// Inferência de tipo
type User = z.infer<typeof userSchema>;
// {
// id: number;
// name: string;
// email: string;
// age?: number;
// role: 'user' | 'admin';
// createdAt: Date;
// }
Validação
// parse: lança exceção em caso de falha
const user = userSchema.parse({
id: 1,
name: 'Alice',
email: 'alice@example.com',
role: 'user'
});
// safeParse: retorna resultado como objeto
const result = userSchema.safeParse(input);
if (result.success) {
console.log(result.data);
} else {
console.error(result.error.issues);
}
Transform
const schema = z.string()
.transform(val => val.toLowerCase())
.transform(val => val.trim());
const cleanSchema = z.object({
price: z.string().transform(val => parseFloat(val)),
quantity: z.string().transform(val => parseInt(val, 10))
});
Funcionalidades Avançadas
Refinement
const passwordSchema = z.string()
.min(8, 'A senha deve ter pelo menos 8 caracteres')
.refine(
(val) => /[A-Z]/.test(val),
{ message: 'Inclua pelo menos uma letra maiúscula' }
)
.refine(
(val) => /[0-9]/.test(val),
{ message: 'Inclua pelo menos um número' }
);
// superRefine (retorna múltiplos erros)
const formSchema = z.object({
password: z.string(),
confirmPassword: z.string()
}).superRefine((data, ctx) => {
if (data.password !== data.confirmPassword) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'As senhas não coincidem',
path: ['confirmPassword']
});
}
});
Union e Discriminator
// Union normal
const responseSchema = z.union([
z.object({ status: z.literal('success'), data: z.any() }),
z.object({ status: z.literal('error'), message: z.string() })
]);
// Discriminated union (mais rápido)
const eventSchema = z.discriminatedUnion('type', [
z.object({ type: z.literal('click'), x: z.number(), y: z.number() }),
z.object({ type: z.literal('scroll'), offset: z.number() }),
z.object({ type: z.literal('keypress'), key: z.string() })
]);
Schema Recursivo
interface Category {
name: string;
subcategories: Category[];
}
const categorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
subcategories: z.array(categorySchema)
})
);
Partial e Required
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string()
});
// Tornar todos opcionais
const partialUser = userSchema.partial();
// Tornar apenas campos específicos opcionais
const updateUser = userSchema.partial({
name: true,
email: true
});
// Tornar opcionais obrigatórios
const requiredUser = userSchema.required();
Validação de API
Express
import express from 'express';
import { z } from 'zod';
const createUserSchema = z.object({
body: z.object({
name: z.string(),
email: z.string().email()
}),
query: z.object({
notify: z.string().optional()
})
});
function validate<T extends z.ZodType>(schema: T) {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req);
if (!result.success) {
return res.status(400).json({ errors: result.error.issues });
}
next();
};
}
app.post('/users', validate(createUserSchema), (req, res) => {
// Validado
});
tRPC
import { z } from 'zod';
import { publicProcedure, router } from './trpc';
export const appRouter = router({
createUser: publicProcedure
.input(z.object({
name: z.string().min(1),
email: z.string().email()
}))
.mutation(async ({ input }) => {
return db.user.create({ data: input });
})
});
Integração com Bibliotecas de Formulário
React Hook Form
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(1, 'Nome é obrigatório'),
email: z.string().email('Por favor, insira um endereço de email válido')
});
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema)
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} />
{errors.name && <span>{errors.name.message}</span>}
{/* ... */}
</form>
);
}
Resumo
O Zod 4 tornou a validação de schemas TypeScript ainda mais rápida e fácil de usar. Com integração de inferência de tipos, funcionalidades ricas de validação e compatibilidade com frameworks, é uma ferramenta indispensável para o desenvolvimento de aplicações type-safe.
← Voltar para a lista