I had a second look at this, and it seems to me now that in my comment here, it may be more appropriate to translate foo: ReadOnly[T]
to __setattr__(self, name: Literal["foo"], val: Never) -> None
instead of __setattr__(self, name: Literal["foo"], val: T) -> Never
.
This is compatible with the intended usage here (applying to __setitem__
instead of __setattr__
) and allows for contravariant overriding so that subclasses can choose to make a ReadOnly
mutable.
I think if one wants to forbid writing for subtypes entirely, then Final[ReadOnly[T]]
would be the correct thing to do.