Another possibility you could maybe discuss in “Rejected Alternatives” is something like:
from typing import ReadOnly, TypedDict
class Movie(TypedDict):
name: ReadOnly[str]
year: ReadOnly[int | None]
where any field marked as ReadOnly[] may not be mutated.
I think this would give you the same features? The main downside I see is the verbose syntax; especially if you combine it with NotRequired:
from typing import NotRequired, ReadOnly, TypedDict
class Movie(TypedDict):
name: ReadOnly[str]
year: ReadOnly[NotRequired[int | None]]