typing_inspect
Runtime introspection helpers for Python's typing module — detect generics, unions, and type variables reliably.
Repository Health
Technical Analysis
typing_inspect is a small, focused Python library that exposes an experimental API for inspecting types defined in the standard typing module at runtime. The standard library’s typing internals shift between Python versions and are not designed for external inspection, so tools that need to reason about generic types, unions, type variables, or forward references at runtime are left writing brittle version-specific checks against private typing internals.
The library normalizes those differences behind a stable set of predicate and accessor functions — is_generic_type, is_union_type, is_optional_type, get_origin, get_args, get_parameters, and more — so callers can ask “is this a generic type?” or “what are this type’s arguments?” without touching typing’s private _GenericAlias, _SpecialForm, or version-gated internals directly.
It is maintained by a CPython typing module contributor and is widely depended on by type-checking, serialization, and validation tooling that needs to introspect annotations rather than just evaluate them.
What You Get
- Type predicates -
is_generic_type,is_union_type,is_optional_type,is_tuple_type,is_callable_type,is_literal_type,is_final_type,is_typevar,is_classvar,is_new_type, andis_forward_reffor classifying any typing construct - Origin and argument extraction -
get_origin,get_args,get_last_origin,get_last_args, andget_parametersto unpack a subscripted generic back into its base type and type arguments - TypeVar introspection -
get_boundandget_constraintsto read aTypeVar’s bound and constraint set - TypedDict support -
typed_dict_keysto read the field names and types declared on aTypedDict - Cross-version compatibility shims - internal handling for the differences between pre-PEP 560, PEP 560, and PEP 604 (
X | Yunion) typing implementations across Python 3.7 through 3.14
Common Use Cases
- Runtime validation libraries - a data-validation library walks a dataclass’s or Pydantic-style model’s annotations, using
is_union_type/is_optional_typeandget_argsto build per-field validators forOptional[int],Union[str, int], or generic containers - Serialization frameworks - a (de)serializer needs to know a field’s declared generic arguments (e.g.
List[MyModel]) to recursively serialize its contents, usingget_origin/get_argsinstead of parsing__args__directly - Static-analysis-adjacent tooling - a runtime type-checker or dependency-injection container inspects function signatures and needs to classify each annotation (generic, union, type variable) to decide how to resolve or check it
- Framework introspection utilities - a web or CLI framework generates OpenAPI schemas or CLI argument parsers from type hints and needs
typed_dict_keysorget_parametersto walk nested generic and TypedDict structures
Under The Hood
Architecture
typing_inspect is a single flat module (typing_inspect.py) rather than a package — there is no internal layering because the entire surface area is a set of independent predicate and accessor functions that each pattern-match against typing’s internal representations. The module’s real complexity lives at import time: a long chain of version-gated imports and feature-detection flags (NEW_TYPING, WITH_PIPE_UNION, WITH_FINAL, WITH_LITERAL, WITH_CLASSVAR, WITH_NEWTYPE, LEGACY_TYPING) establishes which internal typing classes and constructs are available in the running interpreter, and every public function branches on those flags rather than assuming one implementation. This gives the library a single point of change if typing’s internals shift again, at the cost of every function needing to stay aware of several code paths.
Tech Stack
Pure Python, distributed as a single py_modules entry (not a package) via setuptools. Runtime dependencies are mypy_extensions (for _TypedDictMeta detection) and typing_extensions (for backported constructs like Final, Literal, and TypedDict across Python versions). Declared classifiers cover Python 3.7 through 3.14, and comments in the source note the module still carries vestigial Python 2.7 compatibility notes despite the project having moved on. CI (.github/workflows/ci.yml) runs the test suite across the supported interpreter matrix.
Code Quality
The project ships a single test_typing_inspect.py test module built on unittest/pytest, exercising every public predicate and accessor against real typing constructs (Union, Optional, Generic, TypedDict, ClassVar, NewType, etc.) with version-conditional branches mirroring the library’s own compatibility flags. There is no static type-checking configuration in the repo (ironic for a typing-introspection library) and no type annotations on the module’s own functions, but a .flake8 config enforces basic lint rules. Function and flag naming is consistent and descriptive (is_* for predicates, get_* for accessors, WITH_*/NEW_TYPING for capability flags).
What Makes It Unique
The library’s value is narrow and specific: it is the de facto standard way for third-party tooling to inspect typing constructs without depending on typing’s private, version-unstable internals directly. Rather than reimplementing type logic, it acts as a stable compatibility shim across nearly a decade of typing module evolution — including the PEP 560 rewrite and the PEP 604 X | Y union syntax — which is exactly the kind of maintenance burden individual consuming libraries would otherwise have to each solve themselves.