Thanks, David. I'm really in favour of improving the way required keys are managed in TypedDict and glad you're working on it.
Some feedback to your latest draft:
1. I understand your rationale for not using Optional; however, I am concerned about the potential for confusion in a world where there is both an Optional[...] and Required[...] type hint. Also, the potential for an ugly (but valid?!) Required[Optional[...]] construct.
To reduce confusion we can recommend T|None over Optional[T].
2. Has there been any discussion of using of the Annotated type hint? Example: Annotated[..., Required]? The examples for Annotated cite using it for validation. Having a required key in a dict seems like a good fit! If this option has been considered and rejected, I request it be documented as such in the PEP.
-1. Annotated has a different meaning ("attach third-party data").
3. If we go with Required[...] instead of Annotated[..., ...], would get_type_hints(..., include_extras=False) suppress Required the same way it suppresses Annotated today? If not, this would impose a further burden on code performing dynamic type introspection.
4. When iterating through the TypedDict.__annotations__, will Required[...] be retained there, or would it need to be discovered through __required_keys__, or both?
Together, it seems the best would be to always suppress Required, and only store that info in __required_keys__. Unless I'm missing something subtle (somehow this all sounds like a series of trick questions :-).
5. Could we do away (or at least deprecated) totality in TypedDict, and rely on this mechanism? (and/or possibly codify the use of __required_keys__?)
Do you mean the __total__ attribute? I guess that's already been superseded by __required_keys__ (and __optional_keys__ -- I don't recall why we need both).
6. The PEP states: "It is an error to use `Required[...]` in any location that is not an item of a TypedDict." I'm curious to know how this would be (easily) enforced. I doubt __class_getitem__ would have the necessary context to enforce it.
That should be enforced by the static type checker. Probably worth being explicit about that in the PEP. Such incorrect uses would just be preserved at runtime.