Capítulo 11: Validação de Esquemas de Formulários com Zod
Especialização Frontend com React & TypeScript • React 19, Hooks, Estado Global e Next.js
🗺️ Mapa Conceitual do Tópico
flowchart TD
SCHEMA["Zod Schema (Regras Declarativas)"] --> RESOLVER["@hookform/resolvers/zod"]
RESOLVER --> RHF["React Hook Form"]
SCHEMA --> TS_TYPE["Tipo Estático TypeScript: z.infer<typeof Schema>"]
🏛️ 1. Validação Declarativa Baseada em Schemas
Em vez de escrever validações manuais espalhadas em funções imperativas (if (email.indexOf('@') === -1)), o ecossistema moderno adota a modelagem Schema-First com a biblioteca Zod.
A Fonte Única da Verdade:
O schema Zod valida as entradas em tempo de execução e, simultaneamente, gera o tipo estático do TypeScript através de z.infer<typeof MeuSchema>, eliminando discrepâncias entre o que o compilador espera e o que o usuário realmente digita.
🔗 2. A Ponte: @hookform/resolvers/zod
A biblioteca @hookform/resolvers/zod conecta o Zod diretamente ao React Hook Form. Toda a execução de validação, mapeamento de erros e parsing ocorre de forma automatizada.
📊 3. Comparativo de Estratégias de Validação
| Estratégia | Manutenibilidade | Reutilização no Backend | Tipagem Estática |
|---|---|---|---|
| Validação Manual Inline | Baixa | Impossível (código de UI) | Manual e frágil |
| Regras Nativas do HTML5 | Média | Nula | Inexistente |
| Zod Schemas (Padrão Ouro) | Altíssima | 100% Reutilizável no Node/Fastify | Inferida automaticamente |
⚠️ 4. Armadilhas Comuns e Anti-Padrões de Produção
- Esquecer o Mapeamento de Path no
.refine(): Ao validar se duas senhas coincidem com.refine(), não fornecerpath: ["confirmPassword"]fará o erro ser associado à raiz do formulário e não ao campo visual de confirmação. - Coerção Indevida de Números: Inputs HTML sempre emitem strings no
onChange. Utilizez.coerce.number()para transformar automaticamente strings numéricas em tiposnumber.
💡 5. Diretrizes de Engenharia (Meta & React Docs)
- Compartilhe Schemas entre Front e Back: Em arquiteturas monorepo, coloque schemas de validação em um pacote
@shared/schemasconsumido tanto pelo React quanto pelas APIs Node.js/Fastify. - Mensagens de Erro Humanizadas: Forneça mensagens customizadas em português diretamente nas regras do Zod (
z.string().min(3, "O nome deve conter ao menos 3 caracteres")).
💻 6. Demonstração Arquitetural do Conceito
// loginSchema.ts - Schema corporativo com tipagem inferida
import { z } from "zod";
export const LoginSchema = z.object({
email: z.string().email("Email corporativo inválido").trim(),
password: z.string().min(6, "A senha deve conter no mínimo 6 caracteres")
});
export type LoginFormData = z.infer<typeof LoginSchema>;
📋 7. Cheat-Sheet de Validadores Comuns no Zod
z.string().email(): Valida formato de email internacional.z.string().min(n) / .max(n): Limita caracteres de texto.z.coerce.number(): Converte strings de inputs para números escalares.z.enum(["ADMIN", "USER"]): Validações de opções restritas..refine(fn, options): Regras de negócio personalizadas assíncronas ou síncronas.
🔍 8. Diagnóstico de Performance & React DevTools Profiler
Auditoria de validação de schemas:
- Latência de Validação: Schemas Zod executam em sub-milissegundos (< 0.2ms). Para validações assíncronas contra o banco de dados (ex: verificar duplicidade de CNPJ), aplique debounce de 300ms para evitar sobrecarga de requisições.
🧪 9. Casos de Teste e Cenários de Borda Recomendados
- 🔍 Emails com Caracteres Inválidos: Teste padrões extremos de email para validar a robustez da regex do Zod.
- 🔍 Senhas Sem Coincidência: Valide se a mensagem de erro aparece exatamente sob o campo de confirmação de senha.
- 🔍 Idades Limítrofes: Teste as idades 17 (bloqueada) e 18 (permitida) para validar o
.min(18).