É possível expandir tipos no TypeScript? Mergulhando no desempenho e otimização
Olá, amigo! Se você já escreveu em TypeScript, certamente já se deparou com a pergunta: "É possível expandir tipos da mesma forma que interfaces?" Essa pergunta no Stack Overflow acumulou milhares de visualizações, e não é à toa. Parece simples: interfaces são expandidas com extends, e tipos com interseções (&). Mas existem nuances, e elas afetam diretamente o desempenho e a legibilidade do código.
Hoje vamos entender como expandir tipos no TypeScript, como isso difere das interfaces e como não cometer erros na otimização. Vamos lá!
Type vs Interface: a batalha eterna
Antes de falar sobre expansão, vamos lembrar a diferença. Interfaces são "contratos" que podem ser declarados várias vezes (fusão declarativa), enquanto tipos são apelidos (aliases) para qualquer forma. Ambos podem ser expandidos, mas de maneiras diferentes.
Como expandir interfaces?
Aqui é tudo familiar:
interface Animal { name: string;}
interface Bear extends Animal { honey: boolean;}
const bear: Bear = { name: 'Winnie', honey: true };Simples, elegante, funciona. Mas e se quisermos o mesmo para um tipo?
Como expandir tipos?
Tipos não suportam extends diretamente. Em vez disso, usa-se o operador de interseção (&):
type Animal = { name: string;};
type Bear = Animal & { honey: boolean };
const bear: Bear = { name: 'Winnie', honey: true };Parece semelhante, mas existem armadilhas. Vamos analisá-las com exemplos.
Desempenho: o que é mais rápido?
A pergunta de um milhão: a escolha entre interface extends ou type & afeta a velocidade de compilação e execução? Spoiler: sim, mas não como você pensa.
Compilação: interfaces vencem
O TypeScript compila interfaces mais rápido do que interseções de tipos. Por quê? Interfaces são estruturas "planas" que o compilador pode armazenar em cache e processar linearmente. Interseções de tipos são construções complexas que podem exigir expansão recursiva.
// Interface - rápidainterface A { a: string }interface B extends A { b: number }
// Tipo - mais lentotype A = { a: string }type B = A & { b: number }Em projetos grandes com centenas de tipos, a diferença pode ser perceptível. Mas se você tem 10-20 entidades, não sentirá diferença.
Execução: nenhuma diferença
TypeScript é uma extensão do JavaScript. Em tempo de execução, não existem interfaces nem tipos. Eles existem apenas durante o desenvolvimento. Portanto, a escolha não afeta a velocidade de execução do programa.
Quando os tipos são melhores que as interfaces?
Apesar da potencial lentidão na compilação, os tipos são indispensáveis em alguns cenários:
- Union types — união de tipos (exemplo:
string | number) - Conditional types — tipos condicionais (exemplo:
T extends string ? 'yes' : 'no') - Mapped types — transformação de propriedades (exemplo:
{ [K in keyof T]: boolean })
Interfaces não conseguem lidar com isso. Mas se você precisa apenas expandir um objeto — interfaces são a melhor escolha.
Otimização: como não atirar no próprio pé
Agora, a parte mais interessante. Como escrever tipos expansíveis sem atrasar a compilação e sem confundir os colegas?
Regra 1: Use interfaces para objetos, tipos para todo o resto
Este é o padrão ouro. Se você está descrevendo a forma de um objeto — use interface. Se precisar de union, intersection ou magia com genéricos — use type.
// Bominterface User { id: number; name: string;}
type Status = 'active' | 'inactive';type Admin = User & { role: 'admin' };<