JavaScript

Guia Completo de TypeScript com Node.js e Express: APIs Tipadas do Zero

7 min de leitura

Guia Completo de TypeScript com Node.js e Express: APIs Tipadas do Zero

Configuração Inicial do Ambiente Antes de iniciar qualquer projeto com TypeScript e Node.js, você precisa configurar o ambiente corretamente. Comece instalando Node.js (versão 16+) e criando um novo diretório para seu projeto. Execute e instale as dependências essenciais: TypeScript, Express e tipos do Node. O arquivo gerado define como o TypeScript será compilado. Ajuste as configurações para ambiente Node.js modificando para e para . Em , adicione para ativar verificações rigorosas de tipo — essencial para APIs robustas. Estrutura de Projeto e Tipagem Uma API bem organizada segue uma arquitetura clara com separação de responsabilidades. Crie a seguinte estrutura: Comece definindo seus tipos e interfaces. No arquivo , declare a estrutura esperada: Essa abordagem garante que toda comunicação de dados seja validada pelo TypeScript em tempo de desenvolvimento, evitando bugs em produção. Criando sua Primeira API REST Tipada Agora vamos construir uma API funcional do zero. No arquivo : Servidor rodando em http://localhost:${PORT} Observe como cada rota possui tipos explícitos

<h2>Configuração Inicial do Ambiente</h2>

<p>Antes de iniciar qualquer projeto com TypeScript e Node.js, você precisa configurar o ambiente corretamente. Comece instalando Node.js (versão 16+) e criando um novo diretório para seu projeto. Execute <code>npm init -y</code> e instale as dependências essenciais: TypeScript, Express e tipos do Node.</p>

<pre><code class="language-bash">npm install express cors dotenv

npm install -D typescript ts-node @types/express @types/node ts-node-dev

npx tsc --init</code></pre>

<p>O arquivo <code>tsconfig.json</code> gerado define como o TypeScript será compilado. Ajuste as configurações para ambiente Node.js modificando <code>target</code> para <code>&quot;ES2020&quot;</code> e <code>module</code> para <code>&quot;commonjs&quot;</code>. Em <code>compilerOptions</code>, adicione <code>&quot;strict&quot;: true</code> para ativar verificações rigorosas de tipo — essencial para APIs robustas.</p>

<h2>Estrutura de Projeto e Tipagem</h2>

<p>Uma API bem organizada segue uma arquitetura clara com separação de responsabilidades. Crie a seguinte estrutura:</p>

<pre><code>src/

├── controllers/

├── routes/

├── models/

├── middleware/

└── index.ts</code></pre>

<p>Comece definindo seus tipos e interfaces. No arquivo <code>src/models/User.ts</code>, declare a estrutura esperada:</p>

<pre><code class="language-typescript">export interface User {

id: number;

name: string;

email: string;

createdAt: Date;

}

export type CreateUserDTO = Omit&lt;User, &#039;id&#039; | &#039;createdAt&#039;&gt;;</code></pre>

<p>Essa abordagem garante que toda comunicação de dados seja validada pelo TypeScript em tempo de desenvolvimento, evitando bugs em produção.</p>

<h2>Criando sua Primeira API REST Tipada</h2>

<p>Agora vamos construir uma API funcional do zero. No arquivo <code>src/index.ts</code>:</p>

<pre><code class="language-typescript">import express, { Express, Request, Response } from &#039;express&#039;;

import cors from &#039;cors&#039;;

const app: Express = express();

const PORT = process.env.PORT || 3000;

app.use(cors());

app.use(express.json());

// Simulando um banco de dados em memória

const users: User[] = [];

let nextId = 1;

app.get(&#039;/users&#039;, (req: Request, res: Response): void =&gt; {

res.json(users);

});

app.post(&#039;/users&#039;, (req: Request, res: Response): void =&gt; {

const { name, email }: CreateUserDTO = req.body;

if (!name || !email) {

res.status(400).json({ error: &#039;Name and email are required&#039; });

return;

}

const newUser: User = {

id: nextId++,

name,

email,

createdAt: new Date()

};

users.push(newUser);

res.status(201).json(newUser);

});

app.get(&#039;/users/:id&#039;, (req: Request, res: Response): void =&gt; {

const user = users.find(u =&gt; u.id === parseInt(req.params.id));

if (!user) {

res.status(404).json({ error: &#039;User not found&#039; });

return;

}

res.json(user);

});

app.listen(PORT, () =&gt; {

console.log(Servidor rodando em http://localhost:${PORT});

});</code></pre>

<p>Observe como cada rota possui tipos explícitos para <code>Request</code> e <code>Response</code>. Isso oferece autocompletar inteligente e previne erros de tipagem.</p>

<h2>Validação e Middleware Tipado</h2>

<p>Validação é crucial para APIs seguras. Crie um middleware tipado em <code>src/middleware/validateUser.ts</code>:</p>

<pre><code class="language-typescript">import { Request, Response, NextFunction } from &#039;express&#039;;

import { CreateUserDTO } from &#039;../models/User&#039;;

export const validateUserData = (

req: Request,

res: Response,

next: NextFunction

): void =&gt; {

const { name, email } = req.body;

if (typeof name !== &#039;string&#039; || name.trim().length === 0) {

res.status(400).json({ error: &#039;Invalid name&#039; });

return;

}

if (typeof email !== &#039;string&#039; || !email.includes(&#039;@&#039;)) {

res.status(400).json({ error: &#039;Invalid email&#039; });

return;

}

next();

};</code></pre>

<p>Agora aplique o middleware na rota POST:</p>

<pre><code class="language-typescript">app.post(&#039;/users&#039;, validateUserData, (req: Request, res: Response): void =&gt; {

// seu código aqui

});</code></pre>

<p>Essa separação mantém o código limpo e reutilizável. TypeScript garante que você não esqueça de chamar <code>next()</code> ou que retorne valores inesperados.</p>

<h2>Tratamento de Erros e Tipos Avançados</h2>

<p>Para APIs profissionais, implemente um manipulador de erros centralizado. Crie <code>src/middleware/errorHandler.ts</code>:</p>

<pre><code class="language-typescript">import { Request, Response, NextFunction } from &#039;express&#039;;

export class ApiError extends Error {

constructor(

public statusCode: number,

message: string

) {

super(message);

this.name = &#039;ApiError&#039;;

}

}

export const errorHandler = (

err: Error,

req: Request,

res: Response,

next: NextFunction

): void =&gt; {

if (err instanceof ApiError) {

res.status(err.statusCode).json({ error: err.message });

return;

}

res.status(500).json({ error: &#039;Internal server error&#039; });

};</code></pre>

<p>Use em seu <code>index.ts</code>:</p>

<pre><code class="language-typescript">app.use(errorHandler);</code></pre>

<p>Tipos genéricos também são poderosos. Para respostas padronizadas:</p>

<pre><code class="language-typescript">interface ApiResponse&lt;T&gt; {

success: boolean;

data?: T;

error?: string;

}

const sendResponse = &lt;T&gt;(res: Response, statusCode: number, data: T): void =&gt; {

res.status(statusCode).json({ success: true, data });

};</code></pre>

<h2>Conclusão</h2>

<p>Você aprendeu que TypeScript transforma Node.js em uma plataforma robusta para APIs. Os três pontos principais são: <strong>(1) Tipagem explícita previne bugs antes do deploy</strong>, garantindo segurança em tempo de desenvolvimento; <strong>(2) Estrutura organizada com separação de responsabilidades</strong> (controllers, models, middleware) escala bem conforme seu projeto cresce; <strong>(3) Validação e tratamento de erros centralizados</strong> mantém o código consistente e profissional. Pratique esses conceitos construindo pequenas APIs e, progressivamente, explore bibliotecas como Zod para validação mais robusta e bancos de dados reais. O investimento inicial em tipagem rigorosa economiza horas de debugging futuramente.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://www.typescriptlang.org/docs/" target="_blank" rel="noopener noreferrer">TypeScript Official Documentation</a></li>

<li><a href="https://expressjs.com/" target="_blank" rel="noopener noreferrer">Express.js Guide</a></li>

<li><a href="https://github.com/goldbergyoni/nodebestpractices" target="_blank" rel="noopener noreferrer">Node.js Best Practices</a></li>

<li><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html" target="_blank" rel="noopener noreferrer">TypeScript Handbook - Advanced Types</a></li>

<li><a href="https://www.digitalocean.com/community/tutorials/typescript-express-tutorial" target="_blank" rel="noopener noreferrer">Building REST APIs with Express and TypeScript</a></li>

</ul>

Comentários

Mais em JavaScript

Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress
Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress

Introdução aos Testes End-to-End Testes end-to-end (E2E) verificam sua aplica...

Dominando Hooks em React: useState, useEffect, useRef e useCallback em Projetos Reais
Dominando Hooks em React: useState, useEffect, useRef e useCallback em Projetos Reais

useState: Gerenciando Estado em Componentes Funcionais O é o hook fundamental...

Boas Práticas de Promises em JavaScript: then, catch, finally e Encadeamento para Times Ágeis
Boas Práticas de Promises em JavaScript: then, catch, finally e Encadeamento para Times Ágeis

O que é uma Promise? Uma Promise é um objeto JavaScript que representa o resu...