Voltar para Artigos
Back-end★ Destaque5 min de leitura

Como criar uma API REST com Node.js e TypeScript do zero

Um guia prático e completo para construir uma API REST robusta utilizando Node.js, Express e TypeScript, com boas práticas de arquitetura, validação e tratamento de erros.

12 de agosto de 2026

Construir uma API REST de qualidade vai muito além de usar express() e sair definindo rotas. Neste artigo, vamos do zero até uma estrutura sólida, com TypeScript, validação, tratamento de erros e organização de pastas que vai te salvar quando o projeto crescer.

Pré-requisitos

  • Node.js 20 LTS ou superior instalado
  • npm ou yarn
  • Conhecimento básico de TypeScript
  • Um editor de código (recomendo VS Code)

Inicializando o projeto

Comece criando a pasta do projeto e inicializando o package.json:

bash
mkdir minha-api && cd minha-api
npm init -y

Agora instale as dependências principais e de desenvolvimento:

bash
npm install express
npm install -D typescript ts-node @types/node @types/express nodemon

Sempre separe as dependências de desenvolvimento das de produção usando -D. Isso mantém seu bundle de produção leve e organizado.

Configurando o TypeScript

Gere o arquivo tsconfig.json e configure as opções essenciais:

bash
npx tsc --init
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "skipLibCheck": true
  },
  "include": ["src"]
}

Estrutura de pastas

Uma boa organização desde o início evita uma enorme dor de cabeça no futuro. Adote esta estrutura:

text
src/
├── controllers/   # Lógica de cada rota
├── middlewares/   # Auth, erros, validação
├── models/        # Interfaces e tipos
├── routes/        # Definição das rotas
├── services/      # Regras de negócio
└── server.ts      # Entry point

Criando o servidor

Entry point da aplicação

O arquivo server.ts é o ponto de entrada da aplicação. Ele deve ser enxuto: apenas inicializa o Express, registra os middlewares globais, monta as rotas e sobe o servidor.

Nota sobre a ordem dos middlewares

O Express processa middlewares na ordem em que são registrados. Por isso, express.json() sempre deve vir antes das rotas, e o middleware de erro sempre deve ser o último.

server.ts
import express from 'express';
import { userRoutes } from './routes/userRoutes';
import { errorHandler } from './middlewares/errorHandler';

const app = express();
const PORT = process.env.PORT ?? 3000;

app.use(express.json());

// Rotas
app.use('/api/users', userRoutes);

// Middleware de erros (sempre por último)
app.use(errorHandler);

app.listen(PORT, () => {
  console.log(`🚀 Servidor rodando na porta ${PORT}`);
});

Tratamento de erros centralizado

Uma das melhores práticas em APIs Express é centralizar o tratamento de erros em um middleware dedicado. Isso evita try/catch duplicado em cada controller:

errorHandler.ts
import type { Request, Response, NextFunction } from 'express';

export class AppError extends Error {
  constructor(
    public message: string,
    public statusCode: number = 500
  ) {
    super(message);
    this.name = 'AppError';
  }
}

export function errorHandler(
  err: Error,
  _req: Request,
  res: Response,
  _next: NextFunction
): void {
  if (err instanceof AppError) {
    res.status(err.statusCode).json({ error: err.message });
    return;
  }

  console.error(err);
  res.status(500).json({ error: 'Erro interno do servidor' });
}

O middleware de erro precisa ter exatamente 4 parâmetros (err, req, res, next) para o Express reconhecê-lo como handler de erro, mesmo que você não use todos eles. Use um prefixo _ nos não usados para evitar warnings do TypeScript.

Definindo as rotas

Organize os verbos HTTP na ordem: GET → POST → PUT → PATCH → DELETE. Isso facilita a leitura e a revisão de código em equipe.

  1. GET / — lista todos os recursos
  2. GET /:id — retorna um recurso específico
  3. POST / — cria um novo recurso
  4. PUT /:id — substitui um recurso completo
  5. DELETE /:id — remove um recurso
userRoutes.ts
import { Router } from 'express';
import { UserController } from '../controllers/UserController';

export const userRoutes = Router();
const controller = new UserController();

userRoutes.get('/', controller.index);
userRoutes.get('/:id', controller.show);
userRoutes.post('/', controller.create);
userRoutes.put('/:id', controller.update);
userRoutes.delete('/:id', controller.destroy);

Conclusão

Com essa estrutura você tem uma base sólida que escala bem: adicionar uma nova feature é só criar um controller, um service e uma rota, sem mexer no que já funciona. Os próximos passos naturais seriam adicionar um ORM (como TypeORM ou Prisma), autenticação JWT e uma camada de validação com Zod ou class-validator.

Quer ver esses próximos passos na prática? Os artigos sobre autenticação JWT e validação com Zod estão a caminho!