TypeScript: Interface do TypeScript (interface)
Última atualização: 2026-08-26
Uma interface é a principal forma pela qual o TypeScript define a estrutura de um objeto — ela descreve “quais propriedades e métodos um objeto deve ter”, mas não fornece uma implementação.
1. Sintaxe básica das interfaces
(1) Definir uma interface
interface User {
name: string;
age: number;
email: string;
}
(2) Como usar a interface
let user: User = {
name: "Charlie",
age: 20,
email: "xiaoming@example.com"
};
(3) Interfaces como parâmetros de função
function greet(user: User): string {
return `Hello,${user.name}!How old are you this year?${user.age} years old。`;
}
console.log(greet({ name: "Diana", age: 22, email: "hong@example.com" }));
Saída:
Hello,Diana!How old are you this year?22 years old。
(4) Métodos para descrever interfaces
As interfaces podem descrever não apenas propriedades, mas também assinaturas de métodos:
interface Animal {
name: string;
speak(): string;
move(distance: number): void;
}
let dog: Animal = {
name: "Wangcai",
speak() { return "Woof!"; },
move(distance) { console.log(`${this.name} Moved ${distance}m`); }
};
console.log(dog.speak()); // "Woof!"
dog.move(10); // "Wangcai Moved 10m"
2. Propriedades opcionais e propriedades somente leitura
(1) Atributo opcional ?
interface Config {
host: string;
port: number;
debug?: boolean; // Optional
timeout?: number; // Optional
}
// Optional attributes may be omitted.
let config: Config = { host: "localhost", port: 3000 };
let config2: Config = { host: "localhost", port: 3000, debug: true };
(2) Propriedade somente leitura readonly
interface Point {
readonly x: number;
readonly y: number;
}
let point: Point = { x: 1, y: 2 };
// point.x = 10; // ❌ Read-only properties cannot be modified.
(3) ReadonlyArray e interfaces
interface TodoList {
readonly name: string;
readonly items: readonly string[]; // items Both the array itself and its contents are read-only.
}
let todo: TodoList = {
name: "Today's Tasks",
items: ["Write code", "Test", "Deployment"]
};
// todo.items.push("New Task"); // ❌ Read-only arrays cannot be modified.
// todo.name = "Tomorrow's Tasks"; // ❌ Read-only properties cannot be modified.
3. Herança de interfaces (extends)
As interfaces podem herdar de outras interfaces por meio de extends para permitir a composição e a reutilização de tipos:
(1) Herança única
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: string;
department: string;
}
let emp: Employee = {
name: "Charlie",
age: 28,
employeeId: "E001",
department: "Engineering Department"
};
(2) Herança múltipla
Uma interface pode herdar de várias interfaces ao mesmo tempo:
interface Serializable {
serialize(): string;
}
interface Loggable {
log(message: string): void;
}
interface Entity extends Serializable, Loggable {
id: number;
}
let item: Entity = {
id: 1,
serialize() { return JSON.stringify({ id: this.id }); },
log(message) { console.log(`[${this.id}] ${message}`); }
};
(3) Substituir propriedades
Uma interface filha pode sobrescrever os tipos de propriedade de uma interface pai, mas deve ser compatível:
interface Base {
data: string | number;
}
interface Derived extends Base {
data: string; // ✅ Narrowing — string is a subtype of string | number
}
▶ Exemplo: Criação de tipos hierárquicos por meio da herança
// Basic Interfaces
interface Shape {
color: string;
}
// Extension Interface
interface Square extends Shape {
sideLength: number;
}
interface Circle extends Shape {
radius: number;
}
// Usage
let square: Square = { color: "Red", sideLength: 10 };
let circle: Circle = { color: "Blue", radius: 5 };
function describeShape(shape: Shape): string {
return `One${shape.color}the graphic`;
}
console.log(describeShape(square)); // "A red shape"
console.log(describeShape(circle)); // "A blue shape"
Saída:
A red shape
A blue shape
4. Fusão de declarações
Uma característica única das interfaces — as interfaces com o mesmo nome unificam automaticamente suas propriedades:
(1) Fusão básica
interface Window {
title: string;
}
interface Window {
count: number;
}
// Equivalent to:
// interface Window {
// title: string;
// count: number;
// }
let win: Window = { title: "Main Window", count: 3 };
(2) Regras para fusão
- Propriedades com o mesmo nome devem ter o mesmo tipo; caso contrário, será gerado um erro.
- Incorporar assinaturas de métodos em métodos sobrecarregados
- As interfaces declaradas posteriormente aparecem no topo da lista de sobrecargas (e têm prioridade maior)
interface Calculator {
compute(a: number, b: number): number;
}
interface Calculator {
compute(a: string, b: string): string;
}
// After the merger compute There are two overloads
let calc: Calculator = {
compute(a: any, b: any): any {
return a + b;
}
};
console.log(calc.compute(1, 2)); // 3
console.log(calc.compute("a", "b")); // "ab"
(3) Aplicação prática: estendendo tipos de terceiros
// For the built-in Window Adding Custom Properties to an Interface
interface Window {
myCustomProperty: string;
}
// It is now safe to use
// window.myCustomProperty = "hello"; // ✅
interface em vez de type para ampliar os tipos das bibliotecas de terceiros — type não suporta união de tipos, mas interface sim.
5. Assinaturas de índice e interfaces
As assinaturas de índice também podem ser usadas em interfaces:
interface StringMap {
[key: string]: string;
}
let translations: StringMap = {
hello: "Hello",
goodbye: "Goodbye",
thanks: "Thank you"
};
// Add a new key-value pair
translations["sorry"] = "I'm sorry";
Quando uma assinatura de índice e atributos conhecidos coexistem, os tipos dos atributos conhecidos devem ser compatíveis:
interface Config {
[key: string]: string | number;
host: string; // ✅ string is a subtype of string | number
port: number; // ✅ number is a subtype of string | number
// debug: boolean; // ❌ boolean No string | number subtypes of
}
6. A diferença entre interfaces e aliases de tipo
Tanto as interfaces quanto os tipos podem definir tipos de objeto, mas há as seguintes diferenças:
| Recurso | interface | tipo |
|---|---|---|
| Tipo de objeto | ✅ Uso principal | ✅ Também pode ser usado para |
| Combinação de extratos | ✅ Compatível | ❌ Não compatível |
| Herança | extends |
& Tipo cruzado |
| Tipo de união | ❌ Não pode ser definido diretamente | ✅ type A = B | C |
| Aliases para tipos básicos | ❌ Não permitido | ✅ type ID = string |
| Propriedades calculadas | ❌ Não compatível | ✅ Compatível |
| instanceof | ✅ classe implementa | ❌ Não é possível |
(1) Quando usar uma interface
- Definir formas de objetos (respostas da API, objetos de configuração, modelos de dados)
- Requer
extendspara herança - Requer uma declaração de fusão (para estender um tipo de terceiros)
- classe implementa (uma classe implementa uma interface)
(2) Quando usar type
- Tipo de composto:
type Status = "active" | "inactive" - Aliases para tipos básicos:
type ID = string | number - Operações avançadas, como tipos condicionais e tipos de mapeamento
- Definições básicas dos tipos de ferramentas
interface para tipos de objeto e type para tipos de união e operações em tipos avançados. Os dois não são mutuamente exclusivos e podem ser usados juntos no mesmo projeto.
▶ Exemplo: Propriedades opcionais e somente leitura na prática
interface UserProfile {
readonly id: number;
name: string;
email: string;
nickname?: string;
readonly createdAt: Date;
}
let user: UserProfile = {
id: 1,
name: "Charlie",
email: "charlie@example.com",
createdAt: new Date()
};
user.name = "Diana"; // ✅ name is mutable
// user.id = 2; // ❌ readonly property
console.log(user.nickname); // undefined (optional)
Saída:
undefined
▶ Exemplo: Estendendo interfaces para composição de tipos
interface Timestamped {
createdAt: Date;
updatedAt: Date;
}
interface Owned {
ownerId: number;
ownerName: string;
}
interface Article extends Timestamped, Owned {
title: string;
content: string;
}
let article: Article = {
title: "Hello TypeScript",
content: "TypeScript is great...",
createdAt: new Date(),
updatedAt: new Date(),
ownerId: 1,
ownerName: "Charlie"
};
console.log(`${article.ownerName}: ${article.title}`);
Saída:
Charlie: Hello TypeScript
❓ Perguntas Frequentes
P: O que devo usar —
interfaceoutype? R: Uma regra prática simples: useinterfacepara definir a “forma de um objeto” e usetypepara definir um “alias de tipo” ou “tipo de união”. Se sua equipe já tiver uma convenção, basta segui-la. Em 90% dos casos, os dois são equivalentes, então não se preocupe demais com isso.
P: Uma interface pode herdar um tipo definido por
type? R: Sim.interface extendspode herdar qualquer alias de tipo de objeto definido portype. Por outro lado,typetambém pode combinar interfaces usando tipos cruzados&. Os dois são totalmente interoperáveis.
P: Quais são os riscos da fusão de declarações? R: A fusão de declarações é um recurso das interfaces, mas também representa um risco potencial — se duas interfaces com o mesmo nome tiverem propriedades que compartilhem o mesmo nome, mas sejam de tipos diferentes, ocorrerá um erro de compilação. No desenvolvimento prático, a fusão de declarações é usada principalmente para estender as definições de tipo (.d.ts) de bibliotecas de terceiros; você deve evitar definir interfaces com o mesmo nome em seu código no dia a dia.
P: Uma interface pode descrever um tipo de função? R: Sim, mas geralmente é mais natural usar
type.interface Fn { (a: string): number }é equivalente atype Fn = (a: string) => number, e este último é mais conciso e intuitivo. Recomendamos o uso detypepara tipos de função.
📖 Resumo
- Uma interface descreve a estrutura de um objeto — suas propriedades, seus tipos e as assinaturas de seus métodos
?indica uma propriedade opcional;readonlyindica uma propriedade somente leitura; as duas podem ser combinadas comoreadonly x?: number- As interfaces são herdadas por meio de
extendse suportam tanto a herança simples quanto a múltipla; as interfaces filhas podem restringir os tipos das propriedades de suas interfaces pai. - Observe que a fusão é um recurso exclusivo das interfaces — interfaces com o mesmo nome são automaticamente fundidas, o que é utilizado para estender tipos de terceiros.
interfaceé adequado para definir formas de objetos, enquantotypeé adequado para tipos de união e operações avançadas; no desenvolvimento cotidiano, os dois costumam ser usados de forma intercambiável.
📝 Exercícios
- Problema básico (Dificuldade ⭐): Defina a interface
Book(título, autor, páginas, isbn?), crie dois objetos “livro” e imprima-os. Observe que isbn é uma propriedade opcional. - Problema avançado (Dificuldade ⭐⭐): Defina a interface base
Shape(com os métodos color e area) e, em seguida, definaCircleeRectanglede forma que cada uma herde de Shape e adicione suas próprias propriedades. Escreva uma função que receba um parâmetro do tipo Shape e chame o método area. - Desafio (Dificuldade: ⭐⭐⭐): Use uma declaração para adicionar um método
last(): T | undefinedà interface embutidaArray<T>. Em seguida, chame esse método em um array real e reflita sobre por que isso requer uma declaração de módulo.