TypeScript: Interface do TypeScript (interface)
Última atualização: 2026-10-22
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
interface ou type?interface para definir a “forma de um objeto” e use type para 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.type?interface extends pode herdar qualquer alias de tipo de objeto definido por type. Por outro lado, type também pode combinar interfaces usando tipos cruzados &. Os dois são totalmente interoperáveis.type. interface Fn { (a: string): number } é equivalente a type Fn = (a: string) => number, e este último é mais conciso e intuitivo. Recomendamos o uso de type para 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.