programandoai

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çãoPrefira
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çaQualquer 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.

Não é 'um substitui o outro' em tudo

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.

Crie um 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.

← Voltar ao índice do curso