Generics em JavaScript: para que servem e como usar para iniciantes

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

O que são Generics em JavaScript e para que servem?

\n\n

Imagine que você está escrevendo uma função que deve funcionar com diferentes tipos de dados — números, strings, objetos. Sem Generics (genéricos), você teria que duplicar o código ou usar any, perdendo o controle sobre os tipos. Generics são um mecanismo que permite criar componentes (funções, classes, interfaces) que funcionam com qualquer tipo de dado, mas mantendo a informação sobre o tipo.

\n\n

Embora JavaScript seja uma linguagem de tipagem dinâmica, no ecossistema Node.js é amplamente utilizado o TypeScript, que adiciona tipagem estática. É no TypeScript que os genéricos se revelam em toda a sua potência. No entanto, compreender seus princípios é útil também para JavaScript puro — especialmente se você escreve bibliotecas ou trabalha com frameworks modernos.

\n\n

Neste artigo, abordaremos:

\n
    \n
  • Para que servem os Generics
  • \n
  • Como declarar e usar genéricos em TypeScript
  • \n
  • Exemplos para Node.js (API, processamento de dados)
  • \n
  • Limitações e melhores práticas
  • \n
\n\n

Fundamentos dos Generics: sintaxe e exemplos básicos

\n\n

Primeiro genérico: função identity

\n\n

O exemplo clássico é uma função que retorna exatamente o que recebeu como entrada:

\n\n
// Sem Generics\nfunction identity(value: any): any {\n  return value;\n}\n\n// Com Generics\nfunction identity<T>(value: T): T {\n  return value;\n}\n\n// Uso\nconst num = identity<number>(42);    // num — number\nconst str = identity<string>('hello'); // str — string\n
\n\n

O símbolo <T> é o parâmetro de tipo. Você pode nomeá-lo como quiser (T, U, Item), mas a tradição recomenda usar T (de Type).

\n\n

Genéricos com múltiplos parâmetros

\n\n

Às vezes é necessário trabalhar com vários tipos simultaneamente:

\n\n
function pair<T, U>(first: T, second: U): [T, U] {\n  return [first, second];\n}\n\nconst result = pair<number, string>(1, 'um');\n// result: [number, string]\n
\n\n

Genéricos em arrow functions (Node.js)

\n\n

No React ou em utilitários, é comum usar arrow functions com genéricos:

\n\n
const wrapInArray = <T>(item: T): T[] => {\n  return [item];\n};\n\nconst arr = wrapInArray('teste'); // arr: string[]\n
\n\n

Aplicação de Generics em projetos reais com Node.js

\n\n

Manipuladores de API com respostas tipadas

\n\n

Imagine que você está escrevendo uma função universal para requisições a APIs. Sem genéricos, você perderia os tipos dos dados:

\n\n
// Ruim: any\nasync function fetchData(url: string): Promise<any> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// Bom: Generics\nasync function fetchData<T>(url: string): Promise<T> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// Uso\ninterface User {\n  id: number;\n  name: string;\n}\n\nconst user = await fetchData<User>('/api/user/1');\nconsole.log(user.name); // TypeScript sabe que name é string\n
\n\n

Coleções de dados tipadas

\n\n

Ao trabalhar com bancos de dados (por exemplo, via Prisma ou Mongoose), os genéricos ajudam a criar repositórios universais:

\n\n
class Repository<T extends { id: number }> {\n  private items: T[] = [];\n\n  add(item: T): void {\n    this.items.push(item);\n  }\n\n  getById(id: number): T | undefined {\n    return this.items.find(item => item.id === id);\n  }\n}\n\n// Uso\ninterface Product {\n  id: number;\n  title: string;\n  price: number;\n}\n\nconst productRepo = new Repository<Product>();\nproductRepo.add({ id: 1, title: 'Notebook', price: 1000 });\nconst laptop = productRepo.getById(1);\n
\n\n

Wrappers para tratamento de erros

\n\n

Função universal para

Blogs

Book Recommendations