Visitar URL original
No (public) way to dynamically introspect if an annotation is a TypedDict · Issue #751 · python/typing · GitHub
Skip to content

No (public) way to dynamically introspect if an annotation is a TypedDict #751

Closed

Description

@pxeger

I want to know the Origin of an annotation. This works fine for basically everything, but there is no way to check if an annotation is a TypedDict subclass without resorting to (semantically) private API (by checking if it is an instance of _TypedDictMeta), because issubclass(x, TypedDict) fails. I believe this is because you don't want people thinking isinstance(x, TypedDict) will work to actually validate the keys on a dict. However, I don't think there's any reason to prevent issubclass on it

https://github.com/python/cpython/blob/1b4552c/Lib/typing.py#L1901

Here is an example use-case:

from typing import Dict, get_origin

def validate(data, annotation) -> bool:
    """check if `data` conforms to the type given in `annotation`"""
    # this works
    if get_origin(annotation) is Dict:
        return isinstance(data, dict)
    # but this doesn't...
    elif is_a_typed_dict(annotation):
        return isinstance(data, dict) and validate_typeddict_keys(data, annotation)

    ...

This could be solved in one of the following ways:

  • allow issubclass on TypedDicts
    • or allow it only on TypedDict itself and not subclasses of it, e.g. using a _root classvar like NamedTuple does for its magic
      • although I see no reason not to allow it in that case either
  • make _TypedDictMeta public API (rename to TypedDictMeta)
  • make get_origin work on TypedDicts (not ideal because it isn't really a type)

Activity

  1. changed the title [-]No (public) way to dynamically introspect if an object is a TypedDict[/-] [+]No (public) way to dynamically introspect if an annotation is a TypedDict[/+] on Sep 14, 2020
  2. gvanrossum commented on Sep 14, 2020

    @gvanrossum
    Member

    This is reasonable. Can you show us a function that when added to typing.py would solve your problem? (E.g. is_typed_dict() -- how should it be implemented?)

  3. pxeger commented on Sep 14, 2020

    @pxeger
    Author

    Simply:

    def is_typed_dict(cls: type) -> bool:
        return isinstance(cls, _TypedDictMeta)

    would do. Is there a reason that we can't just allow issubclass on TypedDicts though?

  4. gvanrossum commented on Sep 14, 2020

    @gvanrossum
    Member

    PEP 589 explicitly rejects supporting isinstance or issubclass for TypedDict, so let's not go there.

    Are you willing to make a contribution? There would actually have to be several -- this should be added to typing.py in the CPython 3.10 stdlib, to typing.py and typing_extensions in the typing repo. (Hm, maybe only to typing_extensions? typing.py there is only relevant for Python versions that are no longer supported, like 2.7 and 3.4.)

  5. pxeger commented on Sep 14, 2020

    @pxeger
    Author

    typing.py there is only relevant for Python versions that are no longer supported, like 2.7 and 3.4.)

    https://github.com/python/typing/#workflow-for-cpython-changes says:

    At Guido's discretion, he will from time to time copy typing.py and test_typing.py from the python/typing GitHub repo to the cpython repo.

    Is that note out of date then?

  6. gvanrossum commented on Sep 14, 2020

    @gvanrossum
    Member

    Ouch, yes. That is totally out of date. The "master" copy of those files now lives in the CPython repo and the version here is only maintained (or at least not killed) for the benefit of Python 2.7 users of mypy and pytype.

  7. pxeger commented on Sep 15, 2020

    @pxeger
    Author

    Should I create a BPO for this? It seems like the CPython pull request workflow is heavily centered around using those issue numbers.

    Done, see bpo-41792

  8. septatrix commented on Jun 8, 2021

    @septatrix
    Contributor

    PEP 589 explicitly rejects supporting isinstance or issubclass for TypedDict, so let's not go there.

    While the given reason is valid for isinstance I think the given reason does not really apply to issubclass and more likely due to TypedDict not having an MRO (as discussed here https://bugs.python.org/issue41249).
    Therefore a subclass check would need to manually inspect annotations and totality. With a MRO or other access to the bases this would not be a problem at all as it is already possible for e.g. NamedTuple and subclassing generic types from collection.abc.
    The reasoning given mainly regards generic aliases like issubclass(Mapping[str, int], dict).

  9. Ark-kun commented on Sep 17, 2025

    @Ark-kun

    I know my comment is too late, but I do not think the is_typeddict should go into the root of the typing module. I think such class-specific methods are too spammy for the module scope. Should we also have typing.is_namedtuple, typing.is_mutablemapping, typing.is_typevar etc? I don't think so.
    I think we either need a single solution that is similar to isinstance or issubclass but works for typing constructs or we should put such class-specific methods into the class itself: typing.TypedDict.is_typeddict(annotation).
    It would be also a great place to put introspection methods (e.g. typing.TypedDict.get_required_keys(annotation), typing.TypedDict.get_optional_keys(annotation) etc).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions