interface: o contrato de um objeto com nome
Repetir o mesmo formato de objeto em cinco funções diferentes é um convite ao erro. Uma interface nomeia esse formato uma única vez.
Estudar esta lição interativa →No Módulo 3, você descreveu o formato de um objeto direto na anotação, algo como { nome: string; preco: number }. Isso funciona bem para um caso isolado, mas imagine esse mesmo formato precisando aparecer em cinco funções diferentes de uma loja: uma para exibir o produto, uma para calcular o frete, uma para aplicar desconto. Copiar e colar o mesmo { nome: string; preco: number } cinco vezes é um convite ao erro: um dia alguém atualiza o formato numa cópia e esquece as outras quatro.
A interface resolve isso dando um nome a esse formato, uma única vez, reutilizável em qualquer lugar do código:
// interface descreve o FORMATO de um objeto: um contrato nomeado e reutilizável.
interface Produto {
nome: string;
preco: number;
emEstoque?: boolean; // propriedade opcional
}
function exibir(produto: Produto): string {
return `${produto.nome}: R$ ${produto.preco}`;
}
console.log(exibir({ nome: "Fone", preco: 129.9 }));Repare em dois detalhes. Primeiro, o nome da interface, Produto, começa com letra maiúscula, seguindo uma convenção quase universal em TypeScript para nomes de tipos. Segundo, a propriedade emEstoque tem um ? depois do nome, exatamente como um parâmetro opcional de função: significa que um objeto pode satisfazer a interface Produto sem ter essa propriedade, e ela valeria undefined se ausente.
Pense numa interface como o formulário padronizado de admissão de uma empresa: em vez de cada departamento inventar seu próprio formulário com campos diferentes, existe um único formulário oficial, nomeado, que todo mundo usa e reconhece. Se um campo precisar mudar, muda-se o formulário uma vez, num lugar só, e todos os departamentos que o usam já recebem a atualização.
Interfaces também podem herdar de outras, com a palavra extends, formando uma interface mais específica que já inclui tudo da original, mais algumas propriedades próprias:
// interfaces podem estender outras, herdando as propriedades:
interface Usuario {
nome: string;
email: string;
}
interface Administrador extends Usuario {
nivel: number;
}
const admin: Administrador = { nome: "Ana", email: "ana@ex.com", nivel: 3 };
console.log(admin);O TypeScript não exige que você declare "este objeto é um Produto" em lugar nenhum. Ele checa: este objeto tem todas as propriedades obrigatórias da interface, com os tipos certos? Se sim, ele já é aceito onde a interface for pedida. É a chamada tipagem estrutural: o que importa é o formato, não uma etiqueta explícita.
// Sua vez! Complete a interface "Tarefa" com titulo (string) e concluida
// (boolean), e use-a como tipo do parâmetro de "descrever".
interface Tarefa {
titulo: string;
}
function descrever(tarefa: Tarefa): string {
return `${tarefa.titulo}: ${tarefa.concluida ? "feita" : "pendente"}`;
}
console.log(descrever({ titulo: "Estudar TS", concluida: false }));Adicione a propriedade que falta na interface.