Python issubclass with Generic Aliases
Python's built-in issubclass() function does not support
parameterized generic aliases, raising a TypeError when
evaluated against them in either argument position. Generic aliases—such
as list[int] or dict[str, Any] introduced via
PEP 585 and typing constructs—are intended primarily for
static analysis and type hinting rather than runtime inheritance checks.
Because generic type parameters undergo type erasure and do not
represent distinct runtime types, standard subclass validation cannot
inspect their nested parameters.
Generic Alias as the
Target (classinfo)
When a parameterized generic alias is passed as the second argument
to issubclass(), Python immediately raises an
exception.
issubclass(list, list[int])
# TypeError: Subscripted generics cannot be used with class and instance checksPython explicitly disallows checking whether a base type or specialized type inherits from a subscripted generic. This check is rejected because generic types rely on runtime type erasure. Validating a subscripted generic at runtime would require either shallow inspections that discard type safety or recursive item checks that introduce severe performance degradation.
Generic Alias as the First Argument
When a generic alias is provided as the first argument,
issubclass() also fails because a generic alias is not an
instance of type.
issubclass(list[int], list)
# TypeError: issubclass() arg 1 must be a classAt runtime, an expression like list[int] instantiates
types.GenericAlias (or typing._GenericAlias),
which acts as a wrapper around the origin type and its type arguments.
Because issubclass() requires its first parameter to be a
true class object (a subtype of type), evaluating the alias
directly results in a validation error.
Why Runtime Generics
Fail in issubclass()
- Type Erasure: Python collections do not retain
runtime guarantees about the types of items they hold. A
list[int]at runtime is simply alist. - Variance and Invariance: Standard runtime
inheritance does not account for generic variance rules. For instance,
determining whether
list[int]is a subclass oflist[object]requires structural subtype evaluation that standardtype.__subclasses__mechanisms do not handle. - Metaclass Separation: Generic aliases are factory metadata containers rather than new classes generated dynamically in the hierarchy.
Inspecting Generic Aliases Correctly
To perform subclass checks on generic types, you must unpack the
underlying origin class using typing.get_origin().
from typing import get_origin
alias = list[int]
origin = get_origin(alias) # Returns <class 'list'>
if origin is not None:
print(issubclass(origin, collections.abc.Sequence)) # TrueExtracting the origin drops the generic arguments (e.g.,
int) and returns the base class (e.g., list),
enabling standard runtime type and subclass evaluation. For complex
runtime checks against nested parameters, dedicated third-party runtime
validation libraries such as typeguard or
beartype should be used instead of
issubclass().