Pular para conteúdo

Aula 19 - Arquitetura de DTOs Tipados e Validação em Tempo de Execução 🛡️

Objetivo Pedagógico

Objetivo: Construção de contratos seguros com Data Transfer Objects (DTOs), sincronizando validação de esquema em tempo de execução com tipagem estática (Zod).


📑 1. Fundamentos Teóricos & Análise Técnica

Um dos desafios mais críticos no desenvolvimento de software em TypeScript é a ilusão de segurança em tempo de execução. Como o TypeScript é completamente apagado (type erasure) durante o processo de compilação, qualquer dado vindo de fontes externas (como requisições HTTP, respostas de APIs de terceiros ou formulários de usuários) entra no sistema sem garantia de conformidade com os tipos definidos no código.

A solução de engenharia para este problema é a unificação de Validação de Esquemas em Tempo de Execução com a inferência automática de tipos estáticos através de bibliotecas como Zod: 1. Esquema como Fonte Única da Verdade: Define-se um esquema declarativo de validação com regras de negócio (formatos, comprimentos mínimos, expressões regulares e validações customizadas). 2. Inferência Estática Automática: O utilitário z.infer<typeof Schema> gera o tipo TypeScript correspondente automaticamente, garantindo que o tipo e a validação nunca fiquem descompassados. 3. Parse Seguro (safeParse): Tratamento gracioso de erros de validação sem disparar exceções inesperadas que derrubem o servidor ou quebrem o frontend.

📐 Arquitetura Conceitual & Diagrama de Fluxo

flowchart LR
    ExternalData["Dados Externos (JSON / HTTP Request)"] --> ZodSchema["Zod Schema (Validação em Tempo de Execução)"]
    ZodSchema -->|safeParse()| Result{"Dados Válidos?"}
    Result -->|Sim: Sucesso| TypedDTO["DTO Estritamente Tipado (z.infer)"]
    Result -->|Não: Falha| ErrorMap["Relatório Estruturado de Erros (ZodError)"]
    TypedDTO --> BusinessLogic["Regras de Negócio Seguras!"]
    style ExternalData fill:#e1f5fe,stroke:#01579b
    style ZodSchema fill:#fff3e0,stroke:#e65100
    style TypedDTO fill:#e8f5e9,stroke:#2e7d32
    style ErrorMap fill:#ffebee,stroke:#c62828

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Zero Type Drift: Impossibilidade de dessincronização entre o modelo de validação real e as interfaces TypeScript. - Sanitização e Coerção Automática: Conversão transparente de strings de formulários para números e datas (z.coerce). - Mensagens de Erro Customizadas: Localização e humanização de mensagens de falha diretamente no esquema. - Transformações Puras: Capacidade de normalizar dados (ex: remover espaços com .trim(), forçar minúsculas) durante a validação.


🛠️ 2. Implementação Prática em TypeScript, DTOs e Zod

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// user.dto.ts (Validação com Zod e Inferência Automática)
import { z } from 'zod';

// 1. Definição do Esquema de Validação em Runtime
export const CreateUserSchema = z.object({
  name: z.string().min(3, 'O nome deve ter no mínimo 3 caracteres').trim(),
  email: z.string().email('E-mail em formato inválido').toLowerCase(),
  age: z.coerce.number().int().min(18, 'O usuário deve ser maior de idade'),
  roles: z.array(z.enum(['admin', 'editor', 'viewer'])).nonempty()
});

// 2. Inferência Automática do Tipo Estático de TypeScript
export type CreateUserDTO = z.infer<typeof CreateUserSchema>;

// 3. Função de Validação Segura
export function validateUserData(payload: unknown): CreateUserDTO {
  const result = CreateUserSchema.safeParse(payload);

  if (!result.success) {
    const errorDetails = result.error.format();
    throw new Error(`Falha de validação nos dados de usuário: ${JSON.stringify(errorDetails)}`);
  }

  // result.data é garantidamente do tipo CreateUserDTO!
  return result.data;
}

💡 Análise Passo a Passo do Código

  1. Esquema Declarativo: CreateUserSchema define as restrições tanto de tipo quanto de domínio em uma única declaração.
  2. Inferência com z.infer: type CreateUserDTO é computado automaticamente sem duplicação manual de interfaces.
  3. SafeParse Resiliente: Garante que dados maliciosos ou corrompidos sejam bloqueados na fronteira do sistema antes de atingir o banco de dados.

🎯 3. Próximos Passos & Sequência Didática