Annotated solution
Published August 4, 2026The solution
type MyReadonly<T> = { readonly [K in keyof T]: T[K] }The common wrong answer
type MyReadonly<T> = { [K in keyof T]: Readonly<T[K]> }This applies Readonly to each *value* instead of to the mapping. For a primitive like string that does nothing at all, so the keys stay mutable and the result is just a copy of T.
Line by line
readonly [K in keyof T]The modifier precedes the key clause, mirroring how you would write
readonly host: stringin an interface. It marks the property, not the type of its value.T[K]The value passes through untouched, which is what keeps this shallow. Recursing here instead is exactly how
DeepReadonlyis built.
Takeaway
Modifiers act on properties; wrapping the value type is a different operation entirely. Confusing the two produces a type that looks right and enforces nothing.

