JavaScript

Guia Completo de Interfaces e Type Aliases em TypeScript na Prática

7 min de leitura

Guia Completo de Interfaces e Type Aliases em TypeScript na Prática

Fundamentos: Type Aliases vs Interfaces Type Aliases e Interfaces são dois mecanismos fundamentais para definir estruturas de dados em TypeScript. Embora sirvam propósitos semelhantes, têm diferenças importantes. Uma Interface é um contrato que descreve a forma de um objeto, enquanto um Type Alias é um sinônimo para qualquer tipo — primitivo, union, tuple ou objeto. A principal diferença prática: interfaces podem ser estendidas e implementadas por classes, enquanto type aliases oferecem maior flexibilidade para trabalhar com unions e tipos complexos. Ambas usam verificação estrutural (duck typing), mas interfaces têm melhor suporte para herança e replicação de declarações. Escolha interfaces quando modelar contratos de dados que classes implementarão; use type aliases para composições de tipos mais complexas. Interfaces na Prática: Padrões e Extensão Interfaces brilham quando você precisa descrever contratos que classes implementarão. Use herança de interfaces para reutilizar estruturas comuns e construir hierarquias de tipos. A extensão de interfaces é feita com a palavra-chave , permitindo composição elegante de comportamentos.

<h2>Fundamentos: Type Aliases vs Interfaces</h2>

<p>Type Aliases e Interfaces são dois mecanismos fundamentais para definir estruturas de dados em TypeScript. Embora sirvam propósitos semelhantes, têm diferenças importantes. Uma <strong>Interface</strong> é um contrato que descreve a forma de um objeto, enquanto um <strong>Type Alias</strong> é um sinônimo para qualquer tipo — primitivo, union, tuple ou objeto.</p>

<p>A principal diferença prática: interfaces podem ser estendidas e implementadas por classes, enquanto type aliases oferecem maior flexibilidade para trabalhar com unions e tipos complexos. Ambas usam verificação estrutural (duck typing), mas interfaces têm melhor suporte para herança e replicação de declarações. Escolha interfaces quando modelar contratos de dados que classes implementarão; use type aliases para composições de tipos mais complexas.</p>

<pre><code class="language-typescript">// Interface: contrato com capacidade de extensão

interface Usuario {

id: number;

nome: string;

email: string;

}

// Type Alias: sinônimo de tipo, aceita unions e primitivos

type StatusPagamento = &#039;pendente&#039; | &#039;processando&#039; | &#039;concluído&#039; | &#039;falhou&#039;;

// Aplicação prática

const usuario: Usuario = {

id: 1,

nome: &#039;Ana Silva&#039;,

email: &#039;ana@example.com&#039;

};

const status: StatusPagamento = &#039;concluído&#039;;</code></pre>

<h2>Interfaces na Prática: Padrões e Extensão</h2>

<p>Interfaces brilham quando você precisa descrever contratos que classes implementarão. Use herança de interfaces para reutilizar estruturas comuns e construir hierarquias de tipos. A extensão de interfaces é feita com a palavra-chave <code>extends</code>, permitindo composição elegante de comportamentos.</p>

<p>Um padrão comum é usar interfaces genéricas para criar reutilizáveis que funcionam com diferentes tipos de dados. Isso reduz duplicação e torna o código mais maintível. Combine interfaces com classes para garantir que objetos sigam um contrato específico.</p>

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

interface Entidade {

id: number;

criadoEm: Date;

atualizadoEm: Date;

}

// Interface estendida

interface Produto extends Entidade {

nome: string;

preco: number;

estoque: number;

}

// Interface genérica

interface Repositorio&lt;T&gt; {

obter(id: number): Promise&lt;T&gt;;

listar(): Promise&lt;T[]&gt;;

criar(item: T): Promise&lt;T&gt;;

atualizar(id: number, item: Partial&lt;T&gt;): Promise&lt;T&gt;;

deletar(id: number): Promise&lt;void&gt;;

}

// Implementação concreta

class RepositorioProduto implements Repositorio&lt;Produto&gt; {

async obter(id: number): Promise&lt;Produto&gt; {

return {

id,

nome: &#039;Notebook&#039;,

preco: 3500,

estoque: 10,

criadoEm: new Date(),

atualizadoEm: new Date()

};

}

async listar(): Promise&lt;Produto[]&gt; {

return [];

}

async criar(item: Produto): Promise&lt;Produto&gt; {

return item;

}

async atualizar(id: number, item: Partial&lt;Produto&gt;): Promise&lt;Produto&gt; {

return { id } as Produto;

}

async deletar(id: number): Promise&lt;void&gt; {}

}</code></pre>

<h2>Type Aliases Avançados: Unions, Intersections e Mapeamento</h2>

<p>Type Aliases excedem interfaces quando você precisa modelar tipos mais complexos. Unions permitem que um valor seja um de vários tipos, intersections combinam múltiplos tipos em um, e tipos mapeados transformam objetos dinamicamente. Esses recursos são essenciais para código TypeScript profissional.</p>

<p>Use unions para descrever valores que podem ser múltiplos estados, como respostas de API que retornam sucesso ou erro. Intersections são úteis para combinar comportamentos de múltiplos tipos. Tipos mapeados extraem propriedades automaticamente, reduzindo boilerplate significativamente.</p>

<pre><code class="language-typescript">// Union Type: múltiplas possibilidades

type Resultado&lt;T&gt; = { sucesso: true; dados: T } | { sucesso: false; erro: string };

// Intersection Type: combinação de tipos

type Usuario = { id: number; nome: string };

type Timestamps = { criadoEm: Date; atualizadoEm: Date };

type UsuarioCompleto = Usuario &amp; Timestamps;

// Tipos Mapeados: transformação dinâmica

type Leitura&lt;T&gt; = {

readonly [K in keyof T]: T[K];

};

type Opcional&lt;T&gt; = {

[K in keyof T]?: T[K];

};

// Aplicação prática

function procesarResultado&lt;T&gt;(resultado: Resultado&lt;T&gt;): void {

if (resultado.sucesso) {

console.log(&#039;Dados:&#039;, resultado.dados);

} else {

console.log(&#039;Erro:&#039;, resultado.erro);

}

}

const respostaApi: Resultado&lt;{ usuario: string }&gt; = {

sucesso: true,

dados: { usuario: &#039;João&#039; }

};

procesarResultado(respostaApi);

// Usando tipos mapeados

const usuario: Leitura&lt;UsuarioCompleto&gt; = {

id: 1,

nome: &#039;Maria&#039;,

criadoEm: new Date(),

atualizadoEm: new Date()

};

const usuarioOpcional: Opcional&lt;Usuario&gt; = { nome: &#039;Pedro&#039; };</code></pre>

<h2>Integrando com Frameworks: Exemplos Reais</h2>

<p>Em aplicações reais, você usará interfaces e type aliases juntos com frameworks populares como Express, React e Nestjs. As interfaces definem contratos de dados enquanto type aliases gerenciam tipos de requisição/resposta e estados complexos. Essa sinergia garante type safety em toda a stack.</p>

<p>Com Express, interfaces descrevem bodies de requisição enquanto type aliases modelam respostas variáveis. No React com TypeScript, interfaces definem props de componentes e type aliases gerenciam estados e eventos. Nestjs oferece decoradores que funcionam perfeitamente com ambas as construções, permitindo validação automática e documentação gerada.</p>

<pre><code class="language-typescript">// Exemplo com Express

import express, { Request, Response } from &#039;express&#039;;

interface CriarProdutoRequest {

nome: string;

preco: number;

descricao?: string;

}

type ApiResponse&lt;T&gt; = { statusCode: number; dados?: T; erro?: string };

const app = express();

app.use(express.json());

app.post(&#039;/produtos&#039;, (req: Request&lt;{}, {}, CriarProdutoRequest&gt;, res: Response&lt;ApiResponse&lt;{ id: number }&gt;&gt;) =&gt; {

const { nome, preco } = req.body;

if (!nome || preco &lt;= 0) {

return res.status(400).json({

statusCode: 400,

erro: &#039;Nome e preço válido são obrigatórios&#039;

});

}

res.status(201).json({

statusCode: 201,

dados: { id: 1 }

});

});

// Exemplo com React

interface ButtonProps {

label: string;

onClick: () =&gt; void;

disabled?: boolean;

}

type ButtonVariant = &#039;primary&#039; | &#039;secondary&#039; | &#039;danger&#039;;

const Button: React.FC&lt;ButtonProps &amp; { variant?: ButtonVariant }&gt; = ({

label,

onClick,

disabled = false,

variant = &#039;primary&#039;

}) =&gt; {

return (

&lt;button onClick={onClick} disabled={disabled} className={btn-${variant}}&gt;

{label}

&lt;/button&gt;

);

};</code></pre>

<h2>Conclusão</h2>

<p>Dominar Interfaces e Type Aliases é fundamental para escrever TypeScript profissional e mantível. <strong>Primeiro ponto:</strong> use interfaces para contratos de dados e quando precisar de herança; use type aliases para composições complexas, unions e tipos mapeados. <strong>Segundo ponto:</strong> combine ambas strategicamente — uma não substitui a outra, elas são complementares na construção de sistemas robustos. <strong>Terceiro ponto:</strong> pratique integrando essas construções com frameworks reais, pois é onde seu verdadeiro valor emerge na prática diária.</p>

<h2>Referências</h2>

<ul>

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

<li><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases" target="_blank" rel="noopener noreferrer">TypeScript Handbook: Type Aliases</a></li>

<li><a href="https://www.oreilly.com/library/view/effective-typescript/9781492053736/" target="_blank" rel="noopener noreferrer">Effective TypeScript by Dan Vanderkam</a></li>

<li><a href="https://www.typescriptlang.org/docs/handbook/2/types-from-types.html" target="_blank" rel="noopener noreferrer">Advanced TypeScript: Generic Patterns</a></li>

<li><a href="https://basarat.gitbook.io/typescript/" target="_blank" rel="noopener noreferrer">TypeScript Deep Dive - Basarat Ali Syed</a></li>

</ul>

Comentários

Mais em JavaScript

Como Usar Funções em JavaScript: Declaração, Expressão, Arrow e Hoisting em Produção
Como Usar Funções em JavaScript: Declaração, Expressão, Arrow e Hoisting em Produção

Declaração de Funções (Function Declaration) A declaração de função é a forma...

Como Usar Novidades do ECMAScript: ES2022, ES2023 e ES2024 na Prática em Produção
Como Usar Novidades do ECMAScript: ES2022, ES2023 e ES2024 na Prática em Produção

ES2022: Top-Level Await e Class Fields O ES2022 trouxe melhorias significativ...

Como Usar Web Storage em JavaScript: localStorage, sessionStorage e IndexedDB em Produção
Como Usar Web Storage em JavaScript: localStorage, sessionStorage e IndexedDB em Produção

Web Storage em JavaScript: localStorage, sessionStorage e IndexedDB A persist...