Médio TypeScript

Acessor genérico com tipos indexados

Enunciado

Implemente uma função genérica pegar que recebe um objeto obj e uma chave chave (do tipo keyof T) e retorna o valor correspondente com o tipo correto (T[K]). Use o objeto produto para testar e imprima os valores retornados.

Requisitos

  • A função deve ser genérica com <T, K extends keyof T>.
  • O retorno deve ser tipado como T[K].
  • O código deve compilar sem erros e imprimir os três valores.

Código inicial

const produto = {
  nome: "Teclado",
  preco: 150.0,
  estoque: 10,
};

// Implemente a função pegar e use-a

Saída esperada

Teclado
150
10
Ver dica

A assinatura é function pegar<T, K extends keyof T>(obj: T, chave: K): T[K]. Dentro, retorne obj[chave].

Mostrar solução
const produto = {
  nome: "Teclado",
  preco: 150.0,
  estoque: 10,
};

// Função genérica que acessa uma propriedade com tipo preciso
function pegar<T, K extends keyof T>(obj: T, chave: K): T[K] {
  return obj[chave];
}

const nome = pegar(produto, "nome");     // string
const preco = pegar(produto, "preco");   // number
const estoque = pegar(produto, "estoque"); // number

console.log(nome);
console.log(preco);
console.log(estoque);

Passo a passo

  1. Definimos produto com três propriedades de tipos diferentes.
  2. A função pegar usa dois parâmetros de tipo: T (o objeto) e K (a chave), restringindo K a keyof T.
  3. O retorno é anotado como T[K], um tipo indexado que representa o tipo da propriedade K em T.
  4. Dentro da função, obj[chave] é seguro porque chave é uma chave válida de T.
  5. Chamamos pegar três vezes; o TypeScript infere K como o literal da string passada.
  6. Os valores retornados têm os tipos corretos: string, number e number.
  7. Imprimimos cada valor.

Por que funciona

O tipo T[K] é um tipo indexado que extrai o tipo da propriedade K do objeto T. Como K é restrito a keyof T, o compilador sabe que a chave existe e que o retorno corresponde ao tipo real da propriedade. Isso evita casts manuais e mantém a segurança de tipos.

Erros comuns

  • Não restringir K: function pegar<T, K>(obj: T, chave: K) permite qualquer chave, e obj[chave] gera erro porque K pode não ser keyof T.
  • Retornar any: anotar : any perde a precisão e não demonstra o conceito.
  • Passar chave inexistente: pegar(produto, "cor") causa erro de compilação, pois "cor" não está em keyof typeof produto.

Outra forma de resolver

Poderia usar obj[chave] sem genéricos, mas perderíamos a tipagem precisa do retorno. A versão genérica é preferível para reutilização.

Saída esperada

Teclado
150
10