Desafio TypeScript
Remapeamento com as: criar setters tipados
Enunciado
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.
Requisitos
- O tipo deve se chamar
Setterse aceitar um parâmetro genéricoT. - Para cada propriedade
K, deve haver um métodosetK(comKcapitalizado). - O método
setKdeve receber um parâmetro do tipoT[K]e retornarvoid. - O tipo resultante não deve ter as propriedades originais, apenas os setters.
Código inicial
type Setters<T> = /* complete aqui */;
// Teste:
interface Usuario {
nome: string;
idade: number;
}
const setters: Setters<Usuario> = {
setNome: (v) => { console.log(`Nome: ${v}`); },
setIdade: (v) => { console.log(`Idade: ${v}`); },
};
setters.setNome("Ana");
setters.setIdade(30);
Saída esperada
Nome: Ana
Idade: 30
Ver dica
Use [K in keyof T as set${Capitalize<string & K>}]: (value: T[K]) => void.
Mostrar solução
type Setters<T> = {
[K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};
// Teste:
interface Usuario {
nome: string;
idade: number;
}
const setters: Setters<Usuario> = {
setNome: (v) => { console.log(`Nome: ${v}`); },
setIdade: (v) => { console.log(`Idade: ${v}`); },
};
setters.setNome("Ana"); // Nome: Ana
setters.setIdade(30); // Idade: 30
Passo a passo
- Definimos
Setters<T>como um mapped type genérico. - Usamos
[K in keyof T as ...]para iterar sobre as chaves e remapeá-las. - A expressão
as \set${Capitalize<string & K>}`cria um novo nome de chave:set` + chave capitalizada. - O tipo
string & Ké necessário porqueKpode serstring | number | symbol;Capitalizesó aceitastring. - O valor associado é uma função
(value: T[K]) => void. - No teste, criamos um objeto
settersque implementa os métodos. - Chamamos
setNomeesetIdade, que imprimem os valores.
Por que funciona
O remapeamento com as permite alterar os nomes das chaves durante a criação do mapped type. A interseção string & K restringe K a string para que Capitalize possa ser aplicado. O tipo resultante tem apenas as chaves remapeadas, cada uma com o tipo de função correto. Isso é útil para gerar APIs de setters ou getters automaticamente.
Erros comuns
- Esquecer
string & K:Capitalize<K>gera erro porqueKpode não serstring. - Usar
Capitalize<K>sem o& string: o TypeScript reclama queKnão satisfaz a restriçãostring. - Não usar template literal:
as 'set' + Knão é válido em tipos; é preciso usar template literal types. - Deixar as propriedades originais: o remapeamento com
assubstitui as chaves; se quiser manter, use interseção comT.
Outra forma de resolver
Se quiser manter as propriedades originais e adicionar setters, use:
type SettersAndProps<T> = T & {
[K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};
Isso é útil quando você precisa tanto dos dados quanto dos setters.
Saída esperada
Nome: Ana
Idade: 30