Funções de seta TypeScript com genéricos: guia completo com exemplos

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

Menos código, mais utilidade: entendendo funções de seta e genéricos em TypeScript



Você já escreveu uma pequena utilidade em TypeScript que precisava funcionar com números, strings e arrays? E logo se deparou com o problema: como fazer com que o tipo de dado seja flexível, mas sem que o TypeScript reclame? A resposta — genéricos (generics, ou tipos generalizados). E se você gosta de sintaxe concisa, provavelmente usa funções de seta.



Mas eis o problema: no Stack Overflow, a pergunta «What is the syntax for Typescript arrow functions with generics?» acumulou milhares de visualizações. Acontece que até desenvolvedores experientes às vezes se confundem com essa combinação aparentemente simples. Neste artigo, vamos entender como escrever corretamente funções de seta TypeScript com genéricos, analisar erros comuns e mostrar como deixar seu código mais limpo e seguro.



Prontos? Vamos lá!



O que são genéricos em funções de seta?



Para começar — uma breve introdução. Genéricos permitem criar componentes (funções, classes, interfaces) que trabalham com diferentes tipos, em vez de um único específico. Em vez de escrever funções separadas para números e strings, você escreve uma — com genérico.



Funções de seta (arrow functions) são uma sintaxe compacta para funções em JavaScript e TypeScript. Quando você as combina com genéricos, obtém uma ferramenta poderosa para criar utilidades reutilizáveis.



// Função comum com genéricofunction identity<T>(arg: T): T {    return arg;}

// Função de seta com genérico — como fica?const arrowIdentity = <T>(arg: T): T => arg;


Simples? Sim, mas há nuances que abordaremos a seguir.



Sintaxe básica: como declarar corretamente uma função de seta TypeScript com genéricos



A maneira mais simples e comum é especificar o parâmetro de tipo (genérico) antes dos parênteses com os argumentos:



const firstElement = <T>(arr: T[]): T | undefined => {    return arr[0];};

// Usoconst num = firstElement([1, 2, 3]); // tipo: number | undefinedconst str = firstElement(['a', 'b']); // tipo: string | undefined


Aqui, <T> é a declaração do genérico. TypeScript inferirá automaticamente o tipo T com base no argumento passado. Se você quiser especificar o tipo explicitamente, também funciona:



const num = firstElement<number>([1, 2, 3]); // Especificamos o tipo explicitamente


Importante: Em JSX (React), essa sintaxe pode conflitar com a marcação. Para esses casos, existem soluções alternativas (abordadas abaixo).



Vários genéricos em uma única função de seta



Você pode usar vários parâmetros de tipo:



const pair = <T, U>(first: T, second: U): [T, U] => {    return [first, second];};

const result = pair(42, 'hello'); // tipo: [number, string]


Isso é especialmente útil ao trabalhar com utilidades como map, reduce ou ao criar wrappers.



Problemas com JSX (React) e suas soluções



Se você escreve em React com TypeScript, notará que a sintaxe <T>(arg) pode ser interpretada pelo compilador como uma tag JSX. Esse é o problema clássico que fez a pergunta no Stack Overflow ganhar tanta popularidade.



Existem duas soluções principais:



1. Usar extends (mesmo quando não necessário)



Adicione extends unknown ou extends Record<string, never>:



const myFunction = <T extends unknown>(arg: T): T => {    return arg;};


Isso indica explicitamente ao TypeScript que <T> é um genérico, e não JSX.



2. Usar sintaxe com vírgula



Em alguns casos, adicionar uma vírgula após o genérico ajuda:



const myFunction = <T,>(arg: T):                

Blogs

Book Recommendations