Pular para o conteúdo principal
Módulo 3 · Lição 2 de 26/14 no curso~15 min
Lições do módulo (2/2)

Genéricos Fundamentais

Genéricos (programação genérica) são um dos recursos mais poderosos do TypeScript. Eles permitem que você escreva componentes, funções e interfaces flexíveis e reutilizáveis ​​que podem funcionar com diferentes tipos de dados, mantendo a máxima segurança de tipo e evitando o uso de any.


Funções genéricas

Pense em um genérico como uma variável para tipos. Vamos considerar uma função que retorna o valor passado a ela como argumento:

TS
function identity<T>(arg: T): T {
  return arg;
}

A letra T (abreviação de Type) é um espaço reservado para o tipo. Quando chamamos identity, o TypeScript captura o tipo do argumento passado e define automaticamente T para esse tipo:

TS
const str = identity<string>('Hello'); // T is string
const num = identity(42); // T is number (automatically inferred!)

Interfaces genéricas e aliases

Os genéricos também podem ser aplicados a interfaces e aliases de tipo para definir contêineres genéricos ou estruturas de dados:

TS
interface Box<T> {
  content: T;
}

const stringBox: Box<string> = { content: 'TypeScript' };
const numberBox: Box<number> = { content: 42 };

Vários parâmetros de tipo

Podemos definir funções ou tipos que usam variáveis ​​de vários tipos (por exemplo, T e U):

TS
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

Restrições genéricas

Às vezes queremos limitar os tipos aceitos por um genérico. Podemos usar a palavra-chave extends para adicionar uma restrição.

Por exemplo, se quisermos que o tipo genérico sempre tenha uma propriedade length (como strings ou arrays):

TS
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): void {
  console.log(arg.length); // Safe! We know arg has 'length'
}

logLength('Hello'); // Valid
logLength([1, 2, 3]); // Valid
// logLength(42); // Error: number does not have a length property!

Experimente você mesmo

Exercício 1: Função de Identidade Genérica

Exercício#ts.m3.l2.e1
Tentativas: 0Carregando…

Complete a função de identidade genérica para que ela aceite um parâmetro de valor do tipo genérico T e o retorne sem modificação.

Carregando editor…
Mostrar dica

O tipo de retorno deve ser o mesmo tipo genérico T do parâmetro.

Solução disponível após 3 tentativas

Exercício 2: Wrapper de caixa genérico

Exercício#ts.m3.l2.e2
Tentativas: 0Carregando…

Defina uma interface genérica chamada Box que aceita um parâmetro de tipo T e possui uma única propriedade chamada content do tipo T.

Carregando editor…
Mostrar dica

Use a interface Box<T> { content: T; } sintaxe.

Solução disponível após 3 tentativas

Exercício 3: Restrição Genérica

Exercício#ts.m3.l2.e3
Tentativas: 0Carregando…

Escreva uma função genérica chamada getLength que aceite um parâmetro arg. arg deve ser restrito a uma interface que possui uma propriedade length (número). A função deve retornar arg.length.

Carregando editor…
Mostrar dica

Declare a função como getLength<T extends HasLength>(arg: T): number e retorne arg.length.

Solução disponível após 3 tentativas

Exercício 4: Par Genérico

Exercício#ts.m3.l2.e4
Tentativas: 0Carregando…

Defina uma interface genérica Pair<T, U> com duas propriedades: a primeira do tipo T e a segunda do tipo U. Em seguida, crie uma função genérica makePair que aceita a primeira (do tipo T) e a segunda (do tipo U) e retorna um objeto implementando Pair<T, U>.

Carregando editor…
Mostrar dica

Use a sintaxe para dois parâmetros genéricos Pair<T, U> e defina makePair adequadamente.

Solução disponível após 3 tentativas