Tipos para os dados: os DTOs
Um DTO (Data Transfer Object) descreve a forma dos dados que entram e
saem da sua API. Você o modela com uma interface ou um type:
// O que o cliente envia para criar um usuário (corpo da requisição)
interface CriarUsuarioDTO {
nome: string;
email: string;
idade?: number; // opcional
}
// O que a API retorna
interface UsuarioResposta {
id: number;
nome: string;
email: string;
}
interface e type são quase intercambiáveis para descrever objetos. Uma
diferença prática: type também nomeia uniões e primitivos
(type Id = number | string), enquanto interface se concentra na forma
de objetos e pode ser estendida.
Tipar req e res
O Express expõe tipos genéricos Request e Response. Os parâmetros da
assinatura deixam você tipar req.params, o corpo e a resposta:
import { Request, Response } from "express";
// Request<Params, ResBody, ReqBody>
app.post(
"/usuarios",
(req: Request<{}, UsuarioResposta, CriarUsuarioDTO>, res: Response<UsuarioResposta>) => {
const { nome, email } = req.body; // req.body: CriarUsuarioDTO
const usuario = { id: 1, nome, email };
res.status(201).json(usuario); // res.json espera UsuarioResposta
}
);
Agora o editor autocompleta req.body.nome e marca um erro se você
tenta res.json({ foo: 1 }), porque não encaixa com UsuarioResposta.
Os parâmetros de rota se tipam da mesma forma:
app.get("/usuarios/:id", (req: Request<{ id: string }>, res: Response) => {
const id = req.params.id; // string (os params SEMPRE chegam como string)
res.json({ id });
});
Genéricos básicos
Um genérico é um tipo com um "buraco" que se preenche ao usá-lo: te permite escrever uma peça reutilizável sem perder a informação de tipos.
interface ApiResponse<T> {
ok: boolean;
data: T;
}
const r1: ApiResponse<UsuarioResposta> = { ok: true, data: { id: 1, nome: "Ada", email: "a@x.com" } };
const r2: ApiResponse<number[]> = { ok: true, data: [1, 2, 3] };
ApiResponse<T> é a mesma envoltura para qualquer data: o <T>
conserva o tipo concreto em cada uso. É exatamente o que o Express faz com
Request<Params, ResBody, ReqBody>.