My code pretty much does what you suggest at the end of your message:

On Mon, 2021-01-11 at 09:22 -0800, Larry Hastings wrote:
Or code can just use inspect.get_type_hints(), which is tied to the Python version
anyway and should always do the right thing.

So far, this has proven mostly[1] sufficient for my needs in a runtime type validation and encoding/decoding library.

[1] A pain point for me is the runtime cost of evaluating 3.10 style type hints, as they're (re-)evaluated for every call to get_type_hints. I've worked around this for now with my own function affix_type_hints, which evaluates get_type_hints once and replaces __annotations__ with the evaluated value. It also addresses a scoping problem where a type hint may reference a value that's not globally scoped for the object being annotated; the hint can be evaluated and affixed within that scope.