Ty­peS­cript generics são usados para gerar códigos reu­ti­li­zá­veis e seguros em termos de tipos. O sistema pode ser aplicado a funções, classes, in­ter­fa­ces e tipos, entre outros.

O que são Ty­peS­cript generics?

Quase toda linguagem de pro­gra­ma­ção oferece fer­ra­men­tas que permitem aos usuários criar modelos de código que podem ser reu­ti­li­za­dos pos­te­ri­or­mente ou em outros projetos. O objetivo não é apenas eco­no­mi­zar tempo, mas também pos­si­bi­li­tar a criação de códigos seguros que se integrem per­fei­ta­mente a novos ambientes. Di­fe­ren­tes com­po­nen­tes, funções e es­tru­tu­ras de dados completas podem ser escritos e re­pli­ca­dos com generics, sem com­pro­me­ter a segurança dos tipos. Em Ty­peS­cript, com o uso de generics, tipos podem ser passados como pa­râ­me­tros para outros tipos, funções e es­tru­tu­ras de dados.

Sintaxe e fun­ci­o­na­mento de Ty­peS­cript generics

A base para se trabalhar com Ty­peS­cript 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 pos­te­ri­or­mente. 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 Ty­peS­cript é utilizado. Esse espaço reservado é também chamado de parâmetro de tipo. É possível colocar vários desses pa­râ­me­tros de tipo entre colchetes. A sintaxe dos Ty­peS­cript 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}`);
}
ty­pes­cript

Aqui, uti­li­za­mos o nome da função “Fun­ca­o­E­xem­plo” para definir a variável genérica “T”. No código a seguir, de­cla­ra­mos essa variável como uma string:

FuncaoExemplo<string>("Este é um string.");
ty­pes­cript

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
ty­pes­cript

Ty­peS­cript generics com duas variáveis

De forma se­me­lhante, Ty­peS­cript generics funcionam quando duas ou mais variáveis genéricas são usadas como espaços re­ser­va­dos. No exemplo a seguir, uti­li­za­mos as variáveis “T” e “U” como tipos para os pa­râ­me­tros “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});
}
ty­pes­cript

Agora, atri­buí­mos tipos de dados e valores aos espaços re­ser­va­dos. Neste caso, os tipos de dados number e string, assim como os valores “11” e “Jogador”. Este é o código cor­res­pon­dente:

const str = FuncaoExemplo<number, string>(11, "Jogador");
console.log(str);
ty­pes­cript

Exemplos de classes reu­ti­li­zá­veis com Ty­peS­cript generics

Se você quiser usar Ty­peS­cript generics para criar classes reu­ti­li­zá­veis, isso também é possível. No exemplo a seguir, usamos generics para obter um valor numérico. Este é o código cor­res­pon­dente:

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());
ty­pes­cript

Isso gera a seguinte saída:

meuNumero: 11
ty­pes­cript

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;
    }
}
ty­pes­cript

Agora, atri­buí­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}`);
ty­pes­cript

Dessa vez, obtemos a seguinte saída:

Julia Schulz
ty­pes­cript

Se quiser combinar di­fe­ren­tes 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;
    }
}
ty­pes­cript

Os espaços re­ser­va­dos 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}`);
ty­pes­cript

Esta é a saída:

11 Jogador
ty­pes­cript

Ty­peS­cript generics com in­ter­fa­ces

Também é possível, e até re­co­men­dá­vel, utilizar Ty­peS­cript generics em in­ter­fa­ces. O pro­ce­di­mento é se­me­lhante ao de de­cla­ra­ção de uma classe:

interface InterfaceExemplo<T> {
    valor: T;
}
ty­pes­cript

Agora, im­ple­men­ta­mos a interface na classe “Exem­plo­Classe”. Atri­buí­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);
ty­pes­cript

Nossa saída fica assim:

Este é um exemplo com uma interface
ty­pes­cript

Criar arrays genéricos com Ty­peS­cript generics

Também é possível utilizar generics em arrays Ty­peS­cript. 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);
ty­pes­cript

Isso nos dá a seguinte saída:

[9, 13, 6, 7, 10]
ty­pes­cript

Ty­peS­cript generics para tipos con­di­ci­o­nais

Você também pode usar Ty­peS­cript generics em tipos con­di­ci­o­nais. O resultado muda de­pen­dendo do aten­di­mento 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>;
ty­pes­cript

type A é a string “exemplo”e type B é um objeto com a pro­pri­e­dade “nome” e o tipo de dado string. Esses dois tipos são então atri­buí­dos como “Pri­mei­ro­Re­sul­tado” e “Se­gun­do­Re­sul­tado”. Ao ve­ri­fi­car­mos os tipos, veremos que “Pri­mei­ro­Re­sul­tado” recebe o valor true e “Se­gun­do­Re­sul­tado” o valor false.

Dica

Faça im­ple­men­ta­ções di­re­ta­mente pelo GitHub: O Deploy Now da IONOS é a melhor escolha para sites e apli­ca­ti­vos, graças à detecção au­to­má­tica de fra­meworks, con­fi­gu­ra­ção rápida e es­ca­la­bi­li­dade ideal. Escolha o plano certo para o seu projeto.

Ir para o menu principal