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}`);
}
typescript

Aqui, 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.");
typescript

Ao 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. é: string
typescript

TypeScript 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});
}
typescript

Agora, 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);
typescript

Exemplos 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());
typescript

Isso gera a seguinte saída:

meuNumero: 11
typescript

O 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;
    }
}
typescript

Agora, 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}`);
typescript

Dessa vez, obtemos a seguinte saída:

Julia Schulz
typescript

Se 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;
    }
}
typescript

Os 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}`);
typescript

Esta é a saída:

11 Jogador
typescript

TypeScript 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;
}
typescript

Agora, 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);
typescript

Nossa saída fica assim:

Este é um exemplo com uma interface
typescript

Criar 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);
typescript

Isso nos dá a seguinte saída:

[9, 13, 6, 7, 10]
typescript

TypeScript 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>;
typescript

type 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.

Dica

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.

Este artigo foi útil?
Ir para o menu principal