<h2>Arrays em TypeScript: Fundamentos e Aplicações Práticas</h2>
<p>Arrays são um dos tipos de dados mais fundamentais na programação. Em TypeScript, eles vão além da sintaxe simples do JavaScript porque permitem definir o tipo exato de elementos que você armazenará, oferecendo segurança de tipo e melhor intellisense na IDE.</p>
<p>Um array em TypeScript é uma coleção ordenada de elementos do mesmo tipo. Você pode declará-lo de duas formas principais: usando a notação com colchetes (<code>tipo[]</code>) ou usando o genérico <code>Array<tipo></code>. A diferença é apenas sintática; ambas são equivalentes.</p>
<pre><code class="language-typescript">// Duas formas de declarar arrays - ambas válidas
const numeros: number[] = [1, 2, 3, 4, 5];
const nomes: Array<string> = ["Alice", "Bob", "Carlos"];
// TypeScript infere o tipo automaticamente
const mistos = [1, "dois", true]; // any[] (evite isso)
// Solução melhor: seja explícito
const dados: (number | string)[] = [1, "dois", 3, "quatro"];</code></pre>
<p>Os métodos de array como <code>map</code>, <code>filter</code> e <code>reduce</code> são essenciais no dia a dia. Quando usados com tipagem correta, eles previnem bugs silenciosos. Observe como o TypeScript verifica os tipos nos callbacks:</p>
<pre><code class="language-typescript">interface Usuario {
id: number;
nome: string;
idade: number;
}
const usuarios: Usuario[] = [
{ id: 1, nome: "Ana", idade: 28 },
{ id: 2, nome: "Bruno", idade: 35 },
{ id: 3, nome: "Camila", idade: 22 }
];
// map com tipagem correta
const nomesMaiusculos = usuarios.map(usuario => usuario.nome.toUpperCase());
// Resultado: ["ANA", "BRUNO", "CAMILA"]
// filter com lógica de negócio
const maioresDeIdade = usuarios.filter(usuario => usuario.idade >= 18);
// reduce para agregação
const idadeTotal = usuarios.reduce((soma, usuario) => soma + usuario.idade, 0);
console.log(Idade média: ${idadeTotal / usuarios.length}); // 28.33</code></pre>
<h3>Arrays Multidimensionais</h3>
<p>Às vezes você precisa de estruturas mais complexas, como matrizes. A sintaxe é simples, mas a tipagem deve ser clara para evitar confusões:</p>
<pre><code class="language-typescript">// Matriz 2D simples
const matriz: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// Acessando elementos
console.log(matriz[1][2]); // 6
// Array de objetos aninhados
interface Produto {
id: number;
nome: string;
preços: number[];
}
const catalogo: Produto[] = [
{ id: 1, nome: "Notebook", preços: [2500, 2400, 2300] },
{ id: 2, nome: "Mouse", preços: [50, 45, 40] }
];
// Acessar preço histórico
const ultimoPreço = catalogo[0].preços[catalogo[0].preços.length - 1];</code></pre>
<p>---</p>
<h2>Tuplas: Quando a Ordem e o Tipo Importam</h2>
<p>Tuplas são arrays com comprimento fixo e tipos específicos para cada posição. Elas são perfeitas quando você retorna múltiplos valores de uma função ou precisa garantir uma estrutura rígida.</p>
<p>A diferença fundamental entre um array e uma tupla é que a tupla não permite adicionar ou remover elementos além do que foi definido. Isso torna o código mais seguro e autodocumentado, pois qualquer pessoa lendo o tipo sabe exatamente quantas e quais informações esperar.</p>
<pre><code class="language-typescript">// Tupla básica: [nome, idade]
type Pessoa = [string, number];
const joao: Pessoa = ["João", 30];
const maria: Pessoa = ["Maria", 28];
// Erro de compilação - TypeScript previne
// const invalido: Pessoa = ["Pedro"]; // Falta um elemento
// const invalido: Pessoa = ["Pedro", 25, "extra"]; // Elemento extra
// Usando tuplas em funções
function criarUsuario(nome: string, email: string): [string, string, boolean] {
return [nome, email, true];
}
const [nomeUsuario, emailUsuario, ativo] = criarUsuario("Alice", "alice@email.com");
console.log(${nomeUsuario} - ${emailUsuario} - Ativo: ${ativo});</code></pre>
<h3>Tuplas Etiquetadas e Opcionais</h3>
<p>TypeScript permite etiquetar cada posição da tupla, tornando o código muito mais legível. Você também pode marcar elementos como opcionais com o operador <code>?</code>:</p>
<pre><code class="language-typescript">// Tupla etiquetada - nomes descritivos para cada posição
type APIResponse = [status: number, dados: string, timestamp: Date];
const resposta: APIResponse = [200, '{"id": 1}', new Date()];
console.log(Status: ${resposta[0]}); // Status: 200
// Elementos opcionais - útil para retornos variáveis
type ResultadoOperacao = [sucesso: boolean, mensagem?: string, erro?: Error];
const sucesso: ResultadoOperacao = [true];
const falha: ResultadoOperacao = [false, "Operação falhou", new Error("Banco de dados indisponível")];
// Tupla com comprimento mínimo
type ListaComResto = [primeiro: string, segundo: string, ...resto: number[]];
const exemplo: ListaComResto = ["a", "b", 1, 2, 3, 4];</code></pre>
<h3>Tuplas em Casos Reais</h3>
<p>Tuplas brilham quando você precisa retornar múltiplos valores correlacionados. Veja um exemplo prático de uma função que processa um upload:</p>
<pre><code class="language-typescript">interface ArquivoUpload {
nome: string;
tamanho: number;
tipo: string;
}
function processarUpload(arquivo: ArquivoUpload):
[sucesso: boolean, caminhoOuErro: string, tamanhoEmMB?: number]
{
if (arquivo.tamanho > 10 1024 1024) {
return [false, "Arquivo excede 10MB"];
}
if (!["image/jpeg", "image/png"].includes(arquivo.tipo)) {
return [false, "Tipo de arquivo não permitido"];
}
const tamanhoEmMB = arquivo.tamanho / (1024 * 1024);
return [true, /uploads/${arquivo.nome}, tamanhoEmMB];
}
// Usando a tupla retornada
const [ok, info, mb] = processarUpload({
nome: "foto.jpg",
tamanho: 5 1024 1024,
tipo: "image/jpeg"
});
if (ok) {
console.log(Upload bem-sucedido: ${info} (${mb?.toFixed(2)}MB));
} else {
console.log(Erro: ${info});
}</code></pre>
<p>---</p>
<h2>Enums: Valores Nomeados e Segurança de Tipo</h2>
<p>Enums (enumerações) permitem definir um conjunto de constantes nomeadas. Em vez de usar strings ou números mágicos espalhados pelo código, você define uma enum uma vez e a reutiliza. Isso torna o código mais seguro, mantível e legível.</p>
<p>TypeScript oferece dois tipos de enums: numéricos e de string. Cada um tem seus casos de uso ideais. Enums numéricos são compilados para constantes simples, enquanto enums de string são mais verbosos mas oferecem melhor legibilidade.</p>
<pre><code class="language-typescript">// Enum numérico - valores são atribuídos automaticamente (0, 1, 2...)
enum Status {
Pendente, // 0
Aprovado, // 1
Rejeitado // 2
}
let statusPedido: Status = Status.Pendente;
console.log(statusPedido); // 0
// Enum de string - mais legível e explícito
enum Role {
Admin = "ADMIN",
Editor = "EDITOR",
Viewer = "VIEWER"
}
let permissaUsuario: Role = Role.Editor;
console.log(permissaUsuario); // "EDITOR"
// Verificar tipo
if (permissaUsuario === Role.Editor) {
console.log("Acesso de editor concedido");
}</code></pre>
<h3>Enums na Prática: Aplicações em Código Real</h3>
<p>Enums são indispensáveis quando você precisa de um conjunto fechado de opções. Evitam strings espalhadas pela codebase e facilitam refatoração:</p>
<pre><code class="language-typescript">enum TipoPagamento {
Credito = "CREDITO",
Debito = "DEBITO",
Pix = "PIX",
Boleto = "BOLETO"
}
enum StatusPedido {
Cancelado = "CANCELADO",
AguardandoPagamento = "AGUARDANDO_PAGAMENTO",
Processando = "PROCESSANDO",
Entregue = "ENTREGUE"
}
interface Pedido {
id: number;
tipoPagamento: TipoPagamento;
status: StatusPedido;
valor: number;
}
function processarPagamento(pedido: Pedido): boolean {
switch (pedido.tipoPagamento) {
case TipoPagamento.Credito:
console.log("Processando cartão de crédito...");
return true;
case TipoPagamento.Pix:
console.log("Gerando QR Code PIX...");
return true;
case TipoPagamento.Boleto:
console.log("Emitindo boleto...");
return true;
case TipoPagamento.Debito:
console.log("Processando débito...");
return true;
default:
// TypeScript garante que todos os casos foram cobertos
const _nunca: never = pedido.tipoPagamento;
return false;
}
}
// Usando a enum
const meuPedido: Pedido = {
id: 123,
tipoPagamento: TipoPagamento.Pix,
status: StatusPedido.AguardandoPagamento,
valor: 199.90
};
processarPagamento(meuPedido);</code></pre>
<h3>Enums Heterogêneos e Reverse Mapping</h3>
<p>TypeScript permite enums com valores mistos (números e strings), embora isso não seja recomendado. Mais útil é conhecer o reverse mapping automático em enums numéricos:</p>
<pre><code class="language-typescript">// Reverse mapping - acesso bidirecional
enum Direcao {
Cima = 0,
Direita = 1,
Baixo = 2,
Esquerda = 3
}
console.log(Direcao.Cima); // 0
console.log(Direcao[0]); // "Cima"
console.log(Direcao[Direcao.Cima]); // "Cima"
// Útil para debug ou quando você recebe um valor numérico da API
function obterDescricaoDirecao(dir: number): string {
return Direcao[dir]; // Retorna o nome da direção
}
console.log(obterDescricaoDirecao(2)); // "Baixo"</code></pre>
<p>---</p>
<h2>Combinando Arrays, Tuplas e Enums: Um Projeto Completo</h2>
<p>Na prática, esses três conceitos trabalham juntos. Veja um exemplo realista de um sistema de carrinhos de compra:</p>
<pre><code class="language-typescript">// Definir tipos com enum e tupla
enum TamanhoUm {
PP = "PP",
P = "P",
M = "M",
G = "G",
GG = "GG"
}
enum StatusCarrinho {
Vazio = "VAZIO",
Preenchido = "PREENCHIDO",
Finalizado = "FINALIZADO"
}
type ItemCarrinho = [id: number, quantidade: number, preco: number];
interface Produto {
id: number;
nome: string;
tamanho: TamanhoUm;
}
interface Carrinho {
usuario_id: number;
status: StatusCarrinho;
itens: ItemCarrinho[];
dataCriacao: Date;
}
// Funções que usam tudo junto
function adicionarAoCarrinho(
carrinho: Carrinho,
produto: Produto,
quantidade: number,
preco: number
): Carrinho {
const novoItem: ItemCarrinho = [produto.id, quantidade, preco];
return {
...carrinho,
itens: [...carrinho.itens, novoItem],
status: StatusCarrinho.Preenchido
};
}
function calcularTotal(carrinho: Carrinho): number {
return carrinho.itens.reduce((total, [_, quantidade, preco]) => {
return total + (quantidade * preco);
}, 0);
}
function obterResumoCarrinho(carrinho: Carrinho): [status: string, total: number, quantidade: number] {
const total = calcularTotal(carrinho);
const quantidade = carrinho.itens.reduce((acc, [_, qtd]) => acc + qtd, 0);
return [StatusCarrinho[carrinho.status], total, quantidade];
}
// Usando tudo junto
const meuCarrinho: Carrinho = {
usuario_id: 1,
status: StatusCarrinho.Vazio,
itens: [],
dataCriacao: new Date()
};
const produto1: Produto = { id: 1, nome: "Camiseta", tamanho: TamanhoUm.M };
const carrinhoAtualizado = adicionarAoCarrinho(meuCarrinho, produto1, 2, 89.90);
const [status, total, quantidade] = obterResumoCarrinho(carrinhoAtualizado);
console.log(Status: ${status}, Total: R$ ${total.toFixed(2)}, Itens: ${quantidade});
// Saída: Status: PREENCHIDO, Total: R$ 179.80, Itens: 2</code></pre>
<p>Este exemplo mostra como enums fornecem valores seguros, tuplas garantem estrutura de dados e arrays armazenam coleções de forma tipada e eficiente.</p>
<p>---</p>
<h2>Conclusão</h2>
<p>Você aprendeu três pilares fundamentais do TypeScript: <strong>Arrays</strong> oferecem coleções flexíveis e tipadas com métodos poderosos; <strong>Tuplas</strong> garantem estruturas rígidas quando você retorna múltiplos valores ou precisa de uma forma específica; e <strong>Enums</strong> eliminam valores mágicos (strings e números soltos) fornecendo constantes nomeadas e seguras.</p>
<p>O verdadeiro poder está em combinar esses três conceitos. Use arrays para coleções de tamanho variável, tuplas para retornos de múltiplos valores com tipos específicos por posição, e enums para representar estados e valores finitos. Essa combinação não apenas torna seu código mais seguro (TypeScript detectará erros em tempo de compilação), mas também torna muito mais fácil para outros desenvolvedores entender sua intenção.</p>
<p>---</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types" target="_blank" rel="noopener noreferrer">TypeScript Handbook - Arrays and Tuples</a></li>
<li><a href="https://www.typescriptlang.org/docs/handbook/enum.html" target="_blank" rel="noopener noreferrer">TypeScript Handbook - Enums</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" target="_blank" rel="noopener noreferrer">MDN Web Docs - Array Methods</a></li>
<li><a href="https://basarat.gitbook.io/typescript/type-system" target="_blank" rel="noopener noreferrer">TypeScript Deep Dive - Chapter on Types</a></li>
</ul>
<p><!-- FIM --></p>