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 deTe cria um novo tipo com as mesmas chaves.- Modificadores
+e-adicionam ou removemreadonlye?das propriedades. - O remapeamento com
aspermite renomear chaves usando tipos condicionais e template literals. - Mapped types são usados internamente por
Partial,Required,Pick,Recorde outros. - Podem ser combinados com tipos condicionais para criar transformações poderosas.
// 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