Currently, when retrieving TypedDict.__annotations__
with a base that has total=False
, you need to compare with __optional_keys__
to ensure the keys are not required. Since total=False
means that keys are not required by default, does it make sense to annotate them as such beforehand? Otherwise __annotations__
ends up with keys that are annotated as NotRequired
and Required
as well as keys without NotRequired
from total=False
, which seems odd?
Semantically total=False
means the same as annotating every key with NotRequired
.
Are you suggesting that __annotations__
should be transformed automatically to add NotRequired[]
to every key in that case? I would oppose that; in my experience, it’s generally better to keep processing of things like __annotations__
to a minimum at runtime. That way, it’s easier for any tools that want to know exactly what the user wrote. For example, if the runtime has a bug and puts the wrong thing in __annotations__
, such tools might not know what to do any more.
In that case, would you expect get_type_hints
to return the total=False keys annotated correctly?
I think there’s a difference there between what I expect and what I want. I expect get_type_hints()
do all kinds of weird things to the types (turning None into NoneType?). I want it to not do that. Therefore, I have learned to avoid using it.
My main concern now is that if we change get_type_hints()
, that’s likely to break some users. Those users might then get upset at me as I’m one of the maintainers of typing.py
, and I don’t like it when users get upset at me. Also, if we make get_type_hints()
more complicated, that makes it harder to maintain in the future.
Come to think of it, is there a formal reason for why None becomes type(None)? I went sleuthing around for the commit history and didn’t find anything definitive for this behaviour.
None
is such a common annotation we made an exception for it in the syntax, letting users write x: None
instead of x: NoneType
.
But we assumed that this irregularity would be annoying when inspecting annotations at runtime – it’d be more consistent if the runtime types to always be instances of type
. I think we were wrong there, and runtime introspectors are more likely to be surprised than delighted by this choice. But it’s too late to change.