type alias: nomeando qualquer tipo
interface nomeia formatos de objeto. type alias vai além: dá nome a uniões, literais e qualquer combinação de tipos. Cada um tem seu lugar.
Estudar esta lição interativa →A interface que você acabou de aprender tem um limite: ela só descreve o formato de um objeto. Mas nem todo tipo que vale a pena nomear é um objeto. Lembra do union type string | number e da união de literais "pendente" | "pago" | "cancelado" do Módulo 3? Eles também merecem um nome, principalmente se forem usados em vários lugares do código. Para isso existe o type (chamado de type alias, ou "apelido de tipo"):
// type alias: dá nome a QUALQUER tipo, não só a formatos de objeto.
type ID = string | number;
type Status = "pendente" | "pago" | "cancelado";
type Pedido = {
id: ID;
status: Status;
total: number;
};
const pedido: Pedido = { id: 42, status: "pendente", total: 129.9 };
console.log(pedido);Repare que type Pedido = { ... } nomeia um formato de objeto, algo que uma interface também faria. A diferença é que type ID = string | number e type Status = "pendente" | "pago" | "cancelado" nomeiam coisas que uma interface não consegue nomear: uniões de tipos, uniões de literais, e muitas outras combinações que fogem do formato "objeto com propriedades".
Pense numa interface como um molde específico, feito só para bolos: ótimo para o que foi projetado, mas inútil para moldar uma barra de chocolate. O type alias é mais como uma etiqueta que você pode colar em qualquer recipiente, seja um molde de bolo, uma caixa, ou um saco: ela nomeia o que estiver dentro, seja lá qual for a forma.
Então, na prática, qual escolher? A maioria dos times profissionais segue um critério simples: use interface quando estiver descrevendo o formato de um objeto, especialmente se ele puder ser estendido ou "reaberto" no futuro. Use type para uniões, literais, e qualquer tipo que não seja um objeto puro. E, quando um objeto simples não precisa de herança nem de nada especial, as duas opções funcionam quase de forma intercambiável, então a escolha vira mais uma questão de convenção do time do que de necessidade técnica.
// 1) extends também aceita um type alias como base:
type Base = { id: number };
interface Produto extends Base {
nome: string;
}
const caneta: Produto = { id: 1, nome: "Caneta" };
console.log(caneta);
// 2) Com type, o equivalente de "estender" é a interseção (&):
type ProdutoComPreco = Produto & { preco: number };
const caderno: ProdutoComPreco = { id: 2, nome: "Caderno", preco: 12 };
console.log(caderno);
// 3) A diferença real: uma interface pode ser declarada de novo e os campos se somam
// (declaration merging). Com type, repetir o nome é erro (TS2300).
interface Usuario { nome: string }
interface Usuario { email: string }
const ana: Usuario = { nome: "Ana", email: "ana@exemplo.com" };
console.log(ana.nome, ana.email);extends aceita type alias como base; & combina types; e só a interface aceita ser declarada de novo (declaration merging).
Repare no que o exemplo mostra: extends não é exclusivo de interface (uma interface pode estender um type, e uma classe pode usar implements com um), e o type também combina formatos, com a interseção &. A diferença real entre os dois está em outro lugar: uma interface pode ser declarada de novo com o mesmo nome e os campos se somam (declaration merging, usado para ampliar tipos de bibliotecas), enquanto repetir um nome de type é erro (TS2300). E só o type nomeia uniões, literais e tuplas.
| Situação | Prefira |
|---|---|
| Formato de objeto que será estendido ou reaberto (declaration merging) | interface |
| União de tipos ou de literais (status, id misto) | type |
| Objeto simples, sem necessidade de herança | Qualquer um dos dois, por convenção do time |
Um critério prático, não uma regra rígida: as duas ferramentas se sobrepõem em boa parte dos casos simples.
Um erro comum é achar que interface e type são sempre 100% intercambiáveis. Não são: só type nomeia uniões e literais; só interface aceita declaration merging. Fora da interseção (objetos simples), a escolha entre um e outro deixa de ser livre.
type alias chamado Cor como a união de literais "vermelho" | "verde" | "azul", e use-o como o tipo do parâmetro cor da função pintar (em vez de string). Ao final, apenas as três cores da união devem ser aceitas pela função.function pintar(cor: string) {
return `Pintando de ${cor}`;
}
console.log(pintar("vermelho"));
🧩 Este é um exercício com correção automática — abra no app para completá-lo e verificar.