Médio TypeScript
Remover opcionalidade e readonly
Enunciado
Crie um mapped type MutableRequired<T> que remova readonly e ? de todas as propriedades de T. Use os modificadores -readonly e -?.
Requisitos
- O tipo deve se chamar
MutableRequirede aceitar um parâmetro genéricoT. - Todas as propriedades devem ser mutáveis (sem
readonly). - Todas as propriedades devem ser obrigatórias (sem
?). - O tipo deve preservar os tipos originais das propriedades.
Código inicial
type MutableRequired<T> = /* complete aqui */;
// Teste:
interface Config {
readonly host?: string;
readonly port?: number;
}
const cfg: MutableRequired<Config> = { host: "localhost", port: 8080 };
cfg.host = "127.0.0.1"; // deve funcionar
cfg.port = 3000; // deve funcionar
// const cfg2: MutableRequired<Config> = { host: "localhost" }; // deve dar erro (port obrigatório)
Ver dica
Use -readonly [K in keyof T]-?: T[K].
Mostrar solução
type MutableRequired<T> = {
-readonly [K in keyof T]-?: T[K];
};
// Teste:
interface Config {
readonly host?: string;
readonly port?: number;
}
const cfg: MutableRequired<Config> = { host: "localhost", port: 8080 };
cfg.host = "127.0.0.1"; // OK
cfg.port = 3000; // OK
// const cfg2: MutableRequired<Config> = { host: "localhost" }; // Erro: propriedade 'port' está faltando
Passo a passo
- Definimos
MutableRequired<T>como um mapped type genérico. - Usamos
-readonlyantes dos colchetes para remover o modificadorreadonlyde cada propriedade. - Usamos
-?após[K in keyof T]para remover a opcionalidade. - O tipo
T[K]mantém o tipo original de cada propriedade. - No teste, criamos
cfgcom todas as propriedades obrigatórias e mutáveis. - Atribuições a
cfg.hostecfg.portsão permitidas. - Criar
cfg2semportgera erro de compilação.
Por que funciona
Os modificadores -readonly e -? instruem o TypeScript a remover os modificadores correspondentes durante a construção do mapped type. Isso é o oposto de readonly e ?, que os adicionam. O resultado é um tipo com todas as propriedades mutáveis e obrigatórias, equivalente a Required<{ -readonly [K in keyof T]: T[K] }>.
Erros comuns
- Usar
+readonlyem vez de-readonly:+readonlyadiciona readonly, não remove. - Colocar
-?no lugar errado:{ [K in keyof T]-?: T[K] }está correto;{ [K in keyof T]?-: T[K] }é inválido. - Esquecer de remover
readonlye depois tentar atribuir: sereadonlynão for removido, a atribuição falha.
Outra forma de resolver
Combinar tipos utilitários:
type MutableRequired<T> = Required<{ -readonly [K in keyof T]: T[K] }>;
Mas isso ainda requer um mapped type para remover readonly. A solução direta é mais clara.
Saída esperada
Nenhuma saída em tempo de execução; o código demonstra tipagem estática. As atribuições são permitidas e a falta de propriedade obrigatória gera erro de compilação.