TypeScript

Interfaces em TypeScript: Definição, Extensão e Merge Declaration na Prática

7 min de leitura

Interfaces em TypeScript: Definição, Extensão e Merge Declaration na Prática

O que é uma Interface em TypeScript? Uma interface em TypeScript é um contrato que define a estrutura de um objeto. Ela descreve quais propriedades e métodos um objeto deve ter, sem implementação — apenas a assinatura. Pense em uma interface como um molde ou blueprint: você a define, e qualquer classe ou objeto que "implemente" essa interface deve seguir as regras estabelecidas. A grande vantagem é o type checking em tempo de desenvolvimento. O TypeScript verifica se você está usando o objeto corretamente antes mesmo de executar o código. Isso reduz bugs e torna seu código mais seguro e previsível. Diferente de classes, interfaces não existem em tempo de execução — o compilador as remove durante a transpilação para JavaScript. Definição Avançada e Propriedades Opcionais Interfaces podem incluir propriedades opcionais e de apenas leitura, proporcionando controle fino sobre a estrutura esperada. Uma propriedade opcional é marcada com , indicando que o objeto não precisa obrigatoriamente fornecê-la. Propriedades de apenas

<h2>O que é uma Interface em TypeScript?</h2>

<p>Uma interface em TypeScript é um contrato que define a estrutura de um objeto. Ela descreve quais propriedades e métodos um objeto deve ter, sem implementação — apenas a assinatura. Pense em uma interface como um molde ou blueprint: você a define, e qualquer classe ou objeto que &quot;implemente&quot; essa interface deve seguir as regras estabelecidas.</p>

<p>A grande vantagem é o <strong>type checking em tempo de desenvolvimento</strong>. O TypeScript verifica se você está usando o objeto corretamente antes mesmo de executar o código. Isso reduz bugs e torna seu código mais seguro e previsível. Diferente de classes, interfaces não existem em tempo de execução — o compilador as remove durante a transpilação para JavaScript.</p>

<pre><code class="language-typescript">// Definindo uma interface simples

interface Usuario {

id: number;

nome: string;

email: string;

ativo: boolean;

}

// Criando um objeto que segue a interface

const usuario: Usuario = {

id: 1,

nome: &quot;João Silva&quot;,

email: &quot;joao@example.com&quot;,

ativo: true

};

// Se tentar atribuir um objeto incompleto, TypeScript gera erro

const usuarioIncompleto: Usuario = {

id: 2,

nome: &quot;Maria&quot;

// ❌ Erro: propriedades &#039;email&#039; e &#039;ativo&#039; não foram atribuídas

};</code></pre>

<h2>Definição Avançada e Propriedades Opcionais</h2>

<p>Interfaces podem incluir propriedades opcionais e de apenas leitura, proporcionando controle fino sobre a estrutura esperada. Uma propriedade opcional é marcada com <code>?</code>, indicando que o objeto não precisa obrigatoriamente fornecê-la. Propriedades de apenas leitura usam <code>readonly</code>, garantindo que não serão modificadas após a criação.</p>

<p>Também é possível definir assinaturas de métodos dentro da interface, especificando qual o retorno esperado e quais parâmetros o método deve aceitar. Isso cria contratos mais robustos quando você precisa garantir comportamentos específicos em classes ou funções que implementam a interface.</p>

<pre><code class="language-typescript"></code></pre>

<h2>Extensão de Interfaces</h2>

<p>A extensão de interfaces permite reutilizar e construir sobre interfaces já existentes, promovendo código DRY (Don&#039;t Repeat Yourself). Usando a palavra-chave <code>extends</code>, você cria uma nova interface que herda todas as propriedades e métodos de uma ou mais interfaces existentes, adicionando novas propriedades conforme necessário.</p>

<p>Uma interface pode estender múltiplas outras interfaces simultaneamente, criando estruturas complexas a partir de componentes menores e reutilizáveis. Isso é particularmente útil em aplicações grandes onde você tem conceitos base que são expandidos em diferentes contextos. A extensão também permite sobrescrever tipos: uma propriedade pode ser redefinida em uma interface derivada com um tipo mais específico.</p>

<pre><code class="language-typescript">// Interface base

interface Entidade {

readonly id: number;

dataCriacao: Date;

}

// Interface que estende Entidade

interface Usuario extends Entidade {

nome: string;

email: string;

verificarEmail(): Promise&lt;boolean&gt;;

}

// Interface que estende múltiplas interfaces

interface AdminDeSistema extends Usuario {

nivelAcesso: &quot;admin&quot; | &quot;moderador&quot; | &quot;usuario&quot;;

permissoes: string[];

revogarPermissao(permissao: string): void;

}

// Implementação concreta

class Admin implements AdminDeSistema {

readonly id: number;

dataCriacao: Date;

nome: string;

email: string;

nivelAcesso: &quot;admin&quot; | &quot;moderador&quot; | &quot;usuario&quot;;

permissoes: string[];

constructor(

id: number,

nome: string,

email: string,

nivelAcesso: &quot;admin&quot; | &quot;moderador&quot; | &quot;usuario&quot;

) {

this.id = id;

this.dataCriacao = new Date();

this.nome = nome;

this.email = email;

this.nivelAcesso = nivelAcesso;

this.permissoes = [];

}

async verificarEmail(): Promise&lt;boolean&gt; {

// Implementação da verificação

return true;

}

revogarPermissao(permissao: string): void {

this.permissoes = this.permissoes.filter(p =&gt; p !== permissao);

}

}

const admin = new Admin(1, &quot;Carlos&quot;, &quot;carlos@admin.com&quot;, &quot;admin&quot;);

admin.permissoes = [&quot;criar_usuarios&quot;, &quot;deletar_usuarios&quot;];

admin.revogarPermissao(&quot;deletar_usuarios&quot;);

console.log(admin.permissoes); // [&quot;criar_usuarios&quot;]</code></pre>

<h2>Declaration Merging em Interfaces</h2>

<p>Declaration merging (fusão de declarações) é um recurso exclusivo de TypeScript que permite declarar a mesma interface múltiplas vezes, e o compilador as combina automaticamente em uma única interface. Isso é especialmente útil quando você quer estender funcionalidades de tipos existentes ou quando trabalha com código que será integrado de múltiplas fontes.</p>

<p>Quando você declara a mesma interface duas vezes, as propriedades de ambas as declarações são combinadas. Isso funciona apenas com interfaces — classes e tipos não suportam merging. Um caso de uso prático é estender interfaces de bibliotecas externas sem modificar o código original, ou quando você tem múltiplos arquivos que constroem a mesma interface incrementalmente.</p>

<pre><code class="language-typescript"></code></pre>

<h3>Merging com Namespaces</h3>

<p>Declaration merging também funciona ao combinar interfaces com namespaces, permitindo organizar código em módulos lógicos. Essa técnica é comum quando você quer separar tipos relacionados em diferentes espaços de nome para melhor organização.</p>

<pre><code class="language-typescript">// Declarar um namespace com uma interface

namespace Configuracao {

export interface Banco {

host: string;

porta: number;

usuario: string;

senha: string;

}

}

// Declarar uma interface no escopo global com o mesmo nome

interface Configuracao {

ambiente: &quot;producao&quot; | &quot;desenvolvimento&quot;;

}

// Agora você acessa ambas:

const configBanco: Configuracao.Banco = {

host: &quot;localhost&quot;,

porta: 5432,

usuario: &quot;admin&quot;,

senha: &quot;senha123&quot;

};

const config: Configuracao = {

ambiente: &quot;desenvolvimento&quot;

};</code></pre>

<h3>Estendendo Tipos Globais</h3>

<p>Um caso de uso prático do declaration merging é estender interfaces globais fornecidas por bibliotecas, como estender o objeto <code>Window</code> no navegador ou adicionar propriedades ao objeto <code>process</code> do Node.js.</p>

<pre><code class="language-typescript">// Estendendo a interface Window do navegador

declare global {

interface Window {

meuApp: {

versao: string;

inicializar(): void;

};

}

}

// Agora você pode usar:

window.meuApp = {

versao: &quot;1.0.0&quot;,

inicializar() {

console.log(&quot;Aplicação iniciada&quot;);

}

};

// Sem declaration merging, TypeScript reclamaria que

// &#039;meuApp&#039; não existe em Window</code></pre>

<h2>Conclusão</h2>

<p>Interfaces em TypeScript são muito mais que simples documentação: são contratos que garantem segurança de tipo e melhor manutenibilidade. A capacidade de estender interfaces permite construir hierarquias de tipos reutilizáveis e escaláveis, enquanto o declaration merging oferece flexibilidade para integrar e estender código de múltiplas fontes sem duplicação. Dominando esses três pilares — definição, extensão e merging — você terá ferramentas poderosas para escrever código TypeScript profissional e resiliente.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://www.typescriptlang.org/docs/handbook/2/objects.html" target="_blank" rel="noopener noreferrer">TypeScript Official Documentation - Interfaces</a></li>

<li><a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html" target="_blank" rel="noopener noreferrer">TypeScript Handbook - Declaration Merging</a></li>

<li><a href="https://effectivetypescript.com/" target="_blank" rel="noopener noreferrer">Effective TypeScript by Dan Vanderkam - Item 11: Use Type Compatibility to Understand Errors</a></li>

<li><a href="https://devblogs.microsoft.com/typescript/" target="_blank" rel="noopener noreferrer">Microsoft TypeScript Blog - Advanced Types</a></li>

<li><a href="https://blog.logrocket.com/typescript-interfaces-vs-types/" target="_blank" rel="noopener noreferrer">Deep Dive into TypeScript Interfaces - LogRocket Blog</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em TypeScript

Testes de Integração com TypeScript: Banco Real e Fixtures Tipadas: Do Básico ao Avançado
Testes de Integração com TypeScript: Banco Real e Fixtures Tipadas: Do Básico ao Avançado

O que são Testes de Integração e Por Que Importam Testes de integração valida...

Boas Práticas de Mocks com TypeScript: jest-mock-extended e Tipagem de Dependências para Times Ágeis
Boas Práticas de Mocks com TypeScript: jest-mock-extended e Tipagem de Dependências para Times Ágeis

O Problema: Por Que Mocks São Essenciais em Testes Quando você escreve testes...

Dominando Segurança em TypeScript: Tipos que Previnem Vulnerabilidades Comuns em Projetos Reais
Dominando Segurança em TypeScript: Tipos que Previnem Vulnerabilidades Comuns em Projetos Reais

O Poder do Sistema de Tipos do TypeScript na Prevenção de Vulnerabilidades O...