Skip to content

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 fails
isinstance(list[int], type) # False
# ❌ These return weird objects, not types
type(list[int]) # typing._GenericAlias
type(str | None) # typing._UnionGenericAlias
type(Literal['hi']) # typing._LiteralGenericAlias

I 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 fine
type(list) # <class 'type'>
isinstance(list, type) # True
# But generic annotations don't
type(list[int]) # <class 'typing._GenericAlias'>
isinstance(list[int], type) # False
# Unions are even worse
type(str | None) # <class 'typing._UnionGenericAlias'>
isinstance(str | None, type) # False
# Literals too
from typing import Literal
type(Literal['hi']) # <class 'typing._LiteralGenericAlias'>
isinstance(Literal['hi'], type) # False

The 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 False

But 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]) # True
is_type_annotation(str | None) # True
is_type_annotation(Literal['hi']) # True

With 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
pass

The 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:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments