Da trilha de TypeScript Este conceito ainda não saiu como card do dia. ir para o card de hoje

TypeScript Tipos avançados Avançado

Mapped types

Mapped types permitem criar novos tipos a partir de um tipo existente, transformando cada propriedade de forma programática. A sintaxe básica é { [K in keyof T]: ... }, onde K percorre as chaves de T e o tipo resultante tem as mesmas chaves, mas com valores possivelmente modificados.

Podemos adicionar ou remover modificadores como readonly e ? usando + e -. Por exemplo, { [K in keyof T]-?: T[K] } remove a opcionalidade de todas as propriedades.

Além disso, o remapeamento com as permite alterar os nomes das chaves durante a transformação. Por exemplo, { [K in keyof T as get${Capitalize<string & K>}]: () => T[K] } cria métodos getter para cada propriedade.

Mapped types são a base de vários tipos utilitários da biblioteca padrão, como Partial, Pick, Record e Readonly. Dominá-los é essencial para escrever tipos avançados e reutilizáveis em TypeScript.

Pontos-chave

  • [K in keyof T] itera sobre as chaves de T e cria um novo tipo com as mesmas chaves.
  • Modificadores + e - adicionam ou removem readonly e ? das propriedades.
  • O remapeamento com as permite renomear chaves usando tipos condicionais e template literals.
  • Mapped types são usados internamente por Partial, Required, Pick, Record e outros.
  • Podem ser combinados com tipos condicionais para criar transformações poderosas.
mapped_types.ts
// Exemplo de mapped types em TypeScript

type Pessoa = {
  nome: string;
  idade: number;
  email?: string;
};

// 1. Mapped type simples: torna todas as propriedades readonly
type ReadonlyPessoa = {
  readonly [K in keyof Pessoa]: Pessoa[K];
};

// 2. Removendo readonly e opcional com -?
type RequiredPessoa = {
  [K in keyof Pessoa]-?: Pessoa[K];
};

// 3. Remapeamento com as: cria getters
// O tipo `string & K` é necessário para usar Capitalize
type GettersPessoa = {
  [K in keyof Pessoa as `get${Capitalize<string & K>}`]: () => Pessoa[K];
};

// 4. Exemplo de uso
const pessoa: RequiredPessoa = {
  nome: "Ana",
  idade: 30,
  email: "ana@exemplo.com",
};

const getters: GettersPessoa = {
  getNome: () => pessoa.nome,
  getIdade: () => pessoa.idade,
  getEmail: () => pessoa.email,
};

console.log(getters.getNome()); // Ana
console.log(getters.getIdade()); // 30
console.log(getters.getEmail()); // ana@exemplo.com

Exercícios

  1. 1
    Fácil

    Tornar todas as propriedades readonly

    Crie um mapped type ReadonlyAll<T> que transforme todas as propriedades de T em readonly. Use a sintaxe [K in keyof T] e o modificador readonly.

    Resolver
  2. 2
    Médio

    Remover opcionalidade e readonly

    Crie um mapped type MutableRequired<T> que remova readonly e ? de todas as propriedades de T. Use os modificadores -readonly e -?.

    Resolver
  3. 3
    Desafio

    Remapeamento com as: criar setters tipados

    Crie um mapped type Setters<T> que transforme cada propriedade K de T em um método setK que aceita um valor do tipo T[K] e retorna void. Use remapeamento com as e template literals. O nome do método deve ser set seguido da chave capitalizada.

    Resolver

Continue estudando