Fácil TypeScript
Tornar todas as propriedades readonly
Enunciado
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.
Requisitos
- O tipo deve se chamar
ReadonlyAlle aceitar um parâmetro genéricoT. - Todas as propriedades do tipo resultante devem ser
readonly. - O tipo deve preservar os tipos originais das propriedades.
Código inicial
type ReadonlyAll<T> = /* complete aqui */;
// Teste:
interface Pessoa {
nome: string;
idade: number;
}
const p: ReadonlyAll<Pessoa> = { nome: "Ana", idade: 30 };
// p.nome = "Bia"; // deve dar erro
Ver dica
Use readonly [K in keyof T]: T[K].
Mostrar solução
type ReadonlyAll<T> = {
readonly [K in keyof T]: T[K];
};
// Teste:
interface Pessoa {
nome: string;
idade: number;
}
const p: ReadonlyAll<Pessoa> = { nome: "Ana", idade: 30 };
// p.nome = "Bia"; // Erro: Cannot assign to 'nome' because it is a read-only property.
Passo a passo
- Definimos um tipo genérico
ReadonlyAll<T>que recebe um parâmetroT. - Usamos a sintaxe de mapped type
{ [K in keyof T]: T[K] }para iterar sobre as chaves deT. - Adicionamos o modificador
readonlyantes dos colchetes para tornar cada propriedade somente leitura. - O tipo resultante tem as mesmas chaves de
T, mas todas comreadonly. - No teste, criamos um objeto
pdo tipoReadonlyAll<Pessoa>. - Tentar atribuir a
p.nomegera erro de compilação, confirmando que o tipo funciona.
Por que funciona
O mapped type { readonly [K in keyof T]: T[K] } percorre cada chave K de T e cria uma propriedade readonly com o tipo T[K]. O modificador readonly é aplicado a todas as propriedades, impedindo atribuições posteriores. Isso é exatamente o que o tipo utilitário Readonly<T> faz internamente.
Erros comuns
- Esquecer o
readonlyantes dos colchetes:{ [K in keyof T]: T[K] }não torna as propriedades readonly. - Usar
keyof Tsem oin:{ [K keyof T]: T[K] }é sintaxe inválida. - Não usar
T[K]como tipo do valor:{ readonly [K in keyof T]: any }perde a tipagem original.
Outra forma de resolver
Usar o tipo utilitário embutido Readonly<T>:
type ReadonlyAll<T> = Readonly<T>;
É preferível quando você não precisa de customizações adicionais.
Saída esperada
Não há saída em tempo de execução, pois o código apenas demonstra tipagem estática. O erro de compilação ao tentar modificar p.nome é o resultado esperado.