TypeScript generics: Como criar modelos de código reutilizáveis
TypeScript generics são usados para gerar códigos reutilizáveis e seguros em termos de tipos. O sistema pode ser aplicado a funções, classes, interfaces e tipos, entre outros.
O que são TypeScript generics?
Quase toda linguagem de programação oferece ferramentas que permitem aos usuários criar modelos de código que podem ser reutilizados posteriormente ou em outros projetos. O objetivo não é apenas economizar tempo, mas também possibilitar a criação de códigos seguros que se integrem perfeitamente a novos ambientes. Diferentes componentes, funções e estruturas de dados completas podem ser escritos e replicados com generics, sem comprometer a segurança dos tipos. Em TypeScript, com o uso de generics, tipos podem ser passados como parâmetros para outros tipos, funções e estruturas de dados.
Sintaxe e funcionamento de TypeScript generics
A base para se trabalhar com TypeScript generics é o uso de variáveis genéricas. Elas funcionam como uma espécie de espaço reservado e indicam o tipo de dado que será declarado posteriormente. No código, elas são indicadas por uma letra maiúscula qualquer. Durante a criação de um código, essas variáveis devem ser colocadas entre colchetes angulares. A elas é atribuído o nome real do tipo, de modo que, no lugar do espaço reservado, o tipo desejado, interface ou classe TypeScript é utilizado. Esse espaço reservado é também chamado de parâmetro de tipo. É possível colocar vários desses parâmetros de tipo entre colchetes. A sintaxe dos TypeScript generics pode ser observada neste exemplo simples:
function FuncaoExemplo<T>(parametro1: T): void {
console.log(`O tipo de dado do parâmetro ${parametro1} é: ${typeof parametro1}`);
}typescriptAqui, utilizamos o nome da função “FuncaoExemplo” para definir a variável genérica “T”. No código a seguir, declaramos essa variável como uma string:
FuncaoExemplo<string>("Este é um string.");typescriptAo passarmos o valor do parâmetro string para a função, recebemos a seguinte saída:
O tipo de dado do parâmetro Este é um string. é: stringtypescriptTypeScript generics com duas variáveis
De forma semelhante, TypeScript generics funcionam quando duas ou mais variáveis genéricas são usadas como espaços reservados. No exemplo a seguir, utilizamos as variáveis “T” e “U” como tipos para os parâmetros “parametro1” e “parametro2”. Elas são separadas por uma vírgula:
function FuncaoExemplo<T, U>(parametro1: T, parametro2: U): string {
return JSON.stringify({parametro1, parametro2});
}typescriptAgora, atribuímos tipos de dados e valores aos espaços reservados. Neste caso, os tipos de dados number e string, assim como os valores “11” e “Jogador”. Este é o código correspondente:
const str = FuncaoExemplo<number, string>(11, "Jogador");
console.log(str);typescriptExemplos de classes reutilizáveis com TypeScript generics
Se você quiser usar TypeScript generics para criar classes reutilizáveis, isso também é possível. No exemplo a seguir, usamos generics para obter um valor numérico. Este é o código correspondente:
class ValorNumerico<T> {
private _valor: T | undefined;
constructor(private nome: string) {}
public setValor(valor: T) {
this._valor = valor;
}
public getValor(): T | undefined {
return this._valor;
}
public toString(): string {
return `${this.nome}: ${this._valor}`;
}
}
let valor = new ValorNumerico<number>('meuNumero');
valor.setValor(11);
console.log(valor.toString());typescriptIsso gera a seguinte saída:
meuNumero: 11typescriptO princípio também funciona com outros tipos de dados e variáveis genéricas. Você pode observar isso no exemplo a seguir:
class ExemploClasse<T, U> {
primeiroNome: T;
ultimoNome: U;
constructor(primeiroNome: T, ultimoNome: U) {
this.primeiroNome = primeiroNome;
this.ultimoNome = ultimoNome;
}
}typescriptAgora, atribuímos às variáveis o tipo de dado string e os valores previstos:
const pessoa1 = new ExemploClasse<string, string>("Julia", "Schulz");
console.log(`${pessoa1.primeiroNome} ${pessoa1.ultimoNome}`);typescriptDessa vez, obtemos a seguinte saída:
Julia SchulztypescriptSe quiser combinar diferentes tipos de dados, proceda conforme o exemplo a seguir:
class ExemploClasse<T, U> {
numero: T;
palavra: U;
constructor(numero: T, palavra: U) {
this.numero = numero;
this.palavra = palavra;
}
}typescriptOs espaços reservados agora recebem os tipos de dados number e string, bem como seus valores:
const combinacao = new ExemploClasse<number, string>(11, "Jogador");
console.log(`${combinacao.numero} ${combinacao.palavra}`);typescriptEsta é a saída:
11 JogadortypescriptTypeScript generics com interfaces
Também é possível, e até recomendável, utilizar TypeScript generics em interfaces. O procedimento é semelhante ao de declaração de uma classe:
interface InterfaceExemplo<T> {
valor: T;
}typescriptAgora, implementamos a interface na classe “ExemploClasse”. Atribuímos ao parâmetro de tipo “T” o tipo string:
class ExemploClasse implements InterfaceExemplo<string> {
valor: string = "Este é um exemplo com uma interface";
}
const resultado = new ExemploClasse();
console.log(resultado.valor);typescriptNossa saída fica assim:
Este é um exemplo com uma interfacetypescriptCriar arrays genéricos com TypeScript generics
Também é possível utilizar generics em arrays TypeScript. Aqui está um exemplo simples de código, no qual usamos a função reverse para inverter a ordem de números em um array:
function reverse<T>(array: T[]): T[] {
return array.reverse();
}
let numeros: number[] = [10, 7, 6, 13, 9];
let novaOrdem: number[] = reverse(numeros);
console.log(novaOrdem);typescriptIsso nos dá a seguinte saída:
[9, 13, 6, 7, 10]typescriptTypeScript generics para tipos condicionais
Você também pode usar TypeScript generics em tipos condicionais. O resultado muda dependendo do atendimento ou não de uma condição. No exemplo a seguir, essa condição é o tipo de dado string. Este é o código:
type IssoEhUmString<T> = T extends string ? true : false;
type A = "exemplo";
type B = {
nome: string;
};
type PrimeiroResultado = IssoEhUmString<A>;
type SegundoResultado = IssoEhUmString<B>;typescripttype A é a string “exemplo”e type B é um objeto com a propriedade “nome” e o tipo de dado string. Esses dois tipos são então atribuídos como “PrimeiroResultado” e “SegundoResultado”. Ao verificarmos os tipos, veremos que “PrimeiroResultado” recebe o valor true e “SegundoResultado” o valor false.
Faça implementações diretamente pelo GitHub: O Deploy Now da IONOS é a melhor escolha para sites e aplicativos, graças à detecção automática de frameworks, configuração rápida e escalabilidade ideal. Escolha o plano certo para o seu projeto.

