Generics e tipagem em JavaScript: como escrever código sem bugs

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que a tipagem é um superpoder, e não um fardo

\n\n

Imagine: você escreve código, tudo funciona, você está feliz. E então — puf! — no console um erro vermelho: Cannot read property 'name' of undefined. Familiar? Bem-vindo ao mundo do JavaScript sem tipos. Mas há uma boa notícia: o JavaScript moderno (e especialmente o TypeScript) oferece uma ferramenta poderosa — Generics (genéricos). Não é apenas "mais um recurso", mas uma maneira real de tornar o código mais limpo, seguro e compreensível.

\n\n

Neste artigo, vamos explorar o que é tipagem em JavaScript, como funcionam os generics e por que você deve usá-los em todos os seus projetos. Nada de teoria seca — apenas exemplos vivos e dicas práticas.

\n\n

O que são Generics e para que servem?

\n\n

Generics (tipos genéricos) são um mecanismo que permite escrever funções, classes e interfaces que trabalham com diferentes tipos de dados, mantendo uma tipagem estrita. Simplificando: você cria um código "universal" que se adapta automaticamente ao tipo de dados com o qual está trabalhando.

\n\n

Sem genéricos, você escreveria algo como:

\n\n
function identity(arg: any): any {\n    return arg;\n}
\n\n

O problema? any destrói toda a tipagem. Você perde informações sobre o tipo, e o compilador não conseguirá alertá-lo sobre erros. Com Generics é diferente:

\n\n
function identity<T>(arg: T): T {\n    return arg;\n}\n\n// Uso\nlet num = identity<number>(42); // tipo number\nlet str = identity<string>("Olá"); // tipo string
\n\n

Magia? Não, apenas tipagem inteligente. O tipo T é um placeholder que é substituído pelo tipo real quando a função é chamada.

\n\n

Generics vs any: a batalha pela segurança

\n\n

Muitos iniciantes perguntam: "Por que se preocupar com genéricos se posso simplesmente usar any?" A resposta é simples: segurança de tipos não é sobre "ficar bonito", mas sobre prevenir bugs em tempo de execução.

\n\n

Veja este exemplo sem Generics:

\n\n
function getLength(data: any): number {\n    return data.length; // se data for número, haverá erro\n}\n\ngetLength(42); // undefined em tempo de execução\n
\n\n

Com genéricos, você indica explicitamente que a função trabalha com arrays ou strings:

\n\n
function getLength<T extends { length: number }>(data: T): number {\n    return data.length;\n}\n\ngetLength([1,2,3]); // 3\ngetLength("hello"); // 5\n// getLength(42); // Erro de compilação — número não tem length\n
\n\n

Vê a diferença? O erro é capturado na hora de escrever o código, não em produção. Essa é a essência da tipagem avançada.

\n\n

Exemplos práticos de Generics em JavaScript

\n\n

Vamos analisar alguns cenários reais onde os genéricos realmente salvam o dia.

\n\n

1. Funções genéricas para trabalhar com arrays

\n\n

Suponha que você está escrevendo uma utilidade para extrair o primeiro elemento de um array:

\n\n
function first<T>(arr: T[]): T | undefined {\n    return arr[0];\n}\n\nconst numbers = [10, 20, 30];\nconst firstNum = first(numbers); // tipo number | undefined\n\nconst strings = ["a", "b", "c"];\nconst firstStr = first(strings); // tipo string | undefined\n
\n\n

Sem genéricos, você teria que escrever duas funções separadas ou usar any. Com tipagem JavaScript através de Generics — uma função funciona para todos os tipos.

\n\n

2. Classes genéricas para armazenamento de dados

\n\n

Imagine que você está criando um wrapper simples para armazenar um valor:

\n\n
class Box<T> {\n    private content: T;\n\n    constructor(initial: T) {\n        this.content = initial;\n    }\n\n    getValue(): T {\n        return this.content;\n    }\n\n    setValue(value: T): void {\n        this.content = value;\n    }\n}\n\n// Uso\nconst numberBox                

Blogs

Book Recommendations