Introdução: API — não são apenas requisições, é um diálogo
Há muito tempo, na era dos monolitos, os desenvolvedores escreviam backend em PHP ou Java, e o frontend apenas chamava URLs prontas. Tudo era simples, mas lento. Hoje, o ecossistema TypeScript dita novas regras: queremos não apenas trocar dados, mas fazer isso de forma segura, rigorosa e com autocompletar. É aqui que entram em cena três gigantes: REST, GraphQL e gRPC.
Neste artigo, não vamos recontar a documentação. Vamos percorrer cada protocolo do ponto de vista de um profissional que usa TypeScript: veremos exemplos reais de código, compararemos o desempenho e entenderemos qual ferramenta é adequada para o seu projeto. Se você programa em TypeScript e quer aprimorar suas habilidades com API, está no lugar certo.
API REST em TypeScript: o clássico que nunca morre
REST (Representational State Transfer) é o padrão de facto. Simplicidade, métodos HTTP (GET, POST, PUT, DELETE) e recursos. Mas no TypeScript, o REST se revela de uma nova forma: obtemos tipagem rigorosa para requisições e respostas.
Como é um cliente REST tipado
Vamos escrever um cliente mínimo, mas funcional, para API REST em TypeScript. Sem bibliotecas extras — apenas fetch e tipos.
// Tipos para a respostainterface User { id: number; name: string; email: string;}
interface ApiResponse<T> { data: T; status: number; message: string;}
// Cliente tipadoclass RestClient { private baseUrl: string;
constructor(baseUrl: string) { this.baseUrl = baseUrl; }
async get<T>(endpoint: string): Promise<ApiResponse<T>> { const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'GET', headers: { 'Content-Type': 'application/json' }, });
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const data: T = await response.json(); return { data, status: response.status, message: 'Success', }; }
async post<T, U>(endpoint: string, body: U): Promise<ApiResponse<T>> { const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), });
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const data: T = await response.json(); return { data, status: response.status, message: 'Created', }; }}
// Usoconst client = new RestClient('https://jsonplaceholder.typicode.com');
async function fetchUser() { const response = await client.get<User>('/users/1'); console.log(response.data.name); // Autocompletar funciona!}
fetchUser();Como você pode ver, a API REST em TypeScript nos dá controle sobre os tipos em cada etapa. Um erro no nome do campo? O TypeScript o detectará em tempo de compilação.
Quando escolher REST
- Simplicidade — REST é fácil de entender e manter.
- Cache — o cache HTTP funciona nativamente.
- Aplicações CRUD — blogs, lojas, painéis de administração.
Desvantagem: em consultas aninhadas complexas, você ou recebe muitos dados (over-fetching) ou faz N requisições (problema N+1).
GraphQL em TypeScript: flexibilidade e precisão
GraphQL é uma linguagem de consulta criada pelo Facebook. Sua principal característica: você decide quais campos obter. GraphQL TypeScript é uma dupla poderosa que oferece segurança total de tipos no cliente e no servidor.
Escrevendo uma consulta GraphQL com tipagem
Para o exemplo, usaremos a biblioteca graphql-request — um cliente leve para TypeScript.
import { request, gql } from 'grap