DevPath · Aprenda a programar ESPTEN

Node com TypeScript

Tipar uma API Express

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>.

Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← Por que TypeScript no backendTipos úteis e a fronteira runtime →