Why can't you use type for type annotations like list[int]?
Problem
When I tried to use type with type annotations like list[int], I got this:
# ❌ This failsisinstance(list[int], type) # False
# ❌ These return weird objects, not typestype(list[int]) # typing._GenericAliastype(str | None) # typing._UnionGenericAliastype(Literal['hi']) # typing._LiteralGenericAliasI expected isinstance(list[int], type) to return True since list[int] is clearly a type annotation. But it doesn’t work. This has always bugged me - there’s no overarching way to describe a type annotation.
What happened?
I can explain why this happens. When I use modern Python type annotations like list[int], str | None, or Literal['hello'], these aren’t actual type objects at runtime. They’re special annotation objects that don’t inherit from type.
Let me show you what I mean:
# Basic types work finetype(list) # <class 'type'>isinstance(list, type) # True
# But generic annotations don'ttype(list[int]) # <class 'typing._GenericAlias'>isinstance(list[int], type) # False
# Unions are even worsetype(str | None) # <class 'typing._UnionGenericAlias'>isinstance(str | None, type) # False
# Literals toofrom typing import Literaltype(Literal['hi']) # <class 'typing._LiteralGenericAlias'>isinstance(Literal['hi'], type) # FalseThe core problem is that expressions like Literal['hi'], str | None, and list[int] aren’t subclasses of type. They’re internal annotation objects that represent types at compile time but aren’t actual type instances at runtime.
Why this matters
This creates real problems when I try to build generic type utilities. I can’t check if something is a type annotation. I can’t create metaprogramming tools that work with all annotations. The issubclass / isinstance functions no longer work when dealing with annotations.
I tried to work around this with complex code:
def is_type_annotation(annotation): # Before PEP 747: Complex workaround needed try: isinstance(annotation, type) except TypeError: # Handle annotation objects return True return FalseBut this is ugly and doesn’t cover all cases.
PEP 747: TypeForm solution
PEP 747 introduces TypeForm to solve this fundamental limitation. TypeForm provides a unified way to work with type annotations.
# ✅ PEP 747 - TypeForm (coming soon)from typing import TypeForm
def is_type_annotation(anno: TypeForm) -> bool: return True # Works for all annotation types
# ✅ Examples:is_type_annotation(list[int]) # Trueis_type_annotation(str | None) # Trueis_type_annotation(Literal['hi']) # TrueWith TypeForm, I can finally create clean utilities that handle all type annotations uniformly:
def validate_type_annotation(annotation): # Before PEP 747: Complex workaround needed try: isinstance(annotation, type) except TypeError: # Handle annotation objects pass
# After PEP 747: Clean and simple if isinstance(annotation, TypeForm): # Process any type annotation passThe reason
The key reason for this limitation is that modern Python type annotations like list[int], str | None, and Literal['hello'] are implemented as special internal objects (_GenericAlias, _UnionGenericAlias, _LiteralGenericAlias) rather than actual type instances. This allows the type checker to handle them properly at compile time but breaks runtime type checking.
PEP 747’s TypeForm bridges this gap by providing a common interface that works with all annotation types, solving a fundamental inconsistency in Python’s type system.
Summary
In this post, I explained why type(list[int]) fails and how TypeForm fixes it. The key point is that modern Python type annotations aren’t actual type objects at runtime, and PEP 747 introduces TypeForm to provide a unified way to work with all annotation types. This solves the fundamental limitation that has frustrated developers who wanted to use isinstance and similar functions with type annotations.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 PEP 747 Official
- 👨💻 Reddit Discussion
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments