Interfaces e Types Avançados
Aula 2 de 7
Interface
Interface define a estrutura (contrato) de um objeto:
interface Usuario {
id: number;
nome: string;
email: string;
}
const usuario: Usuario = {
id: 1,
nome: "Alice",
email: "[email protected]",
};
extends — Herança de Interfaces
interface Animal {
nome: string;
idade: number;
}
interface Cachorro extends Animal {
raca: string;
late(): void;
}
const rex: Cachorro = {
nome: "Rex",
idade: 3,
raca: "Pastor Alemão",
late: () => console.log("Au au!"),
};
Propriedades Opcionais e Readonly
interface Config {
readonly id: string; // imutável após criação
url: string;
timeout?: number; // opcional
headers?: Record<string, string>;
}
const config: Config = { id: "abc123", url: "https://api.exemplo.com" };
// Erro: Cannot assign to 'id' because it is a read-only property
// config.id = "novo";
Index Signature
interface Dicionario {
[chave: string]: string;
}
const traducoes: Dicionario = {
hello: "olá",
world: "mundo",
};
Type Alias vs Interface
| Característica | Interface | Type |
|---|---|---|
| extends/herança | extends | & (intersection) |
| Declaration merging | Sim | Não |
| Union/Intersection | Não | Sim |
| Utility types (Pick, Omit) | Sim | Sim |
| Tupas e primitivos | Não | Sim |
// Type alias aceita union, tuple e primitivos:
type Status = "ativo" | "inativo";
type ParOrdenado = [number, number];
type ID = string | number;
// Declaration merging (só interface):
interface Pessoa {
nome: string;
}
interface Pessoa {
idade: number;
}
// Resultado: { nome: string; idade: number; }
Utility Types
interface Produto {
id: number;
nome: string;
preco: number;
descricao: string;
categoria: string;
}
// Partial — todas as props opcionais
function atualizarProduto(id: number, dados: Partial<Produto>) {
// dados pode ter qualquer subconjunto de Produto
}
// Required — todas as props obrigatórias
type ProdutoCompleto = Required<Partial<Produto>>;
// Pick — seleciona props específicas
type ProdutoResumo = Pick<Produto, "id" | "nome" | "preco">;
// Omit — exclui props específicas
type ProdutoSemDescricao = Omit<Produto, "descricao" | "categoria">;
// Record — tipo dicionário
type Categorias = Record<string, Produto[]>;
// Exclude — remove tipos de uma union
type Status = "ativo" | "inativo" | "pendente";
type Ativos = Exclude<Status, "inativo" | "pendente">; // "ativo"
// Extract — mantém apenas os tipos especificados
type NumerosOuStrings = string | number | boolean;
type SoStrings = Extract<NumerosOuStrings, string>; // string
satisfies Operator
satisfies verifica se uma expressão satisfaz um tipo sem alterar o tipo inferido:
type Cores = "red" | "green" | "blue";
const paleta = {
fundo: "blue",
texto: "white",
} satisfies Record<string, Cores>;
// paleta.fundo é inferido como "blue" (literal), não como Cores
// mas a verificação garante que só valores Cores foram usados
// Erro: Type '"white"' is not assignable to type 'Cores'
Lab: Tipos Avançados na Prática
interface User {
id: number;
name: string;
email: string;
role: "admin" | "user" | "viewer";
createdAt: Date;
}
type UserCreate = Omit<User, "id" | "createdAt">;
type UserUpdate = Partial<UserCreate>;
type UserResponse = Pick<User, "id" | "name" | "email" | "role">;
function createUser(data: UserCreate): User {
return {
id: Date.now(),
createdAt: new Date(),
...data,
};
}
function updateUser(id: number, data: UserUpdate): void {
console.log(`Atualizando usuário ${id}:`, data);
}
function listUsers(): UserResponse[] {
return [];
}
# Verificar tipos com tsc
npx tsc --noEmit
Prefira
interfacepara objetos/classes (declaration merging, mensagens de erro melhores). Usetypepara unions, tuples e primitivos.