type MyReadonly<T> = { readonly [K inkeyof T]: T[K] }
El error más común
type MyReadonly<T> = { [K inkeyof T]: Readonly<T[K]> }
Esto aplica `Readonly` a cada *valor* en lugar de al mapeo. Para un primitivo como `string` no hace nada, así que las claves siguen siendo mutables y el resultado es una copia de `T`.
Línea por línea
readonly [K in keyof T]
El modificador precede a la cláusula de clave, igual que escribirías `readonly host: string` en una interfaz. Marca la propiedad, no el tipo de su valor.
T[K]
El valor pasa intacto, que es lo que lo mantiene superficial. Recurrir aquí es exactamente cómo se construye `DeepReadonly`.
Para recordar
Los modificadores actúan sobre propiedades; envolver el tipo del valor es otra operación distinta. Confundirlas produce un tipo que parece correcto y no impone nada.