Python typing-extensions — Core Concepts
What is typing-extensions?
typing-extensions is a PyPI package maintained by the CPython core developers. It provides backports of new typing module features to older Python versions, enabling libraries and applications to use modern type hints without requiring the latest runtime.
Why it exists
Python’s typing module evolves with each release:
- 3.10:
ParamSpec,TypeAlias,TypeGuard - 3.11:
Self,TypeVarTuple,Never,assert_type - 3.12:
TypeAliasType,override,TypedDictwithUnpack - 3.13:
TypeIs,ReadOnly,NoDefault
Most production codebases support multiple Python versions (e.g., 3.9-3.13). Without typing-extensions, they’d be limited to the features available in their oldest supported version.
How to use it
Installation
pip install typing-extensions
Import pattern
# For features not in your minimum Python version
from typing_extensions import Self, override, TypedDict
# Common conditional import pattern for libraries
import sys
if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override
Most projects skip the conditional and just import from typing_extensions unconditionally — it works on all versions and uses the stdlib implementation when available.
Key features available through typing-extensions
Self (PEP 673, stdlib in 3.11)
For methods returning the current class:
from typing_extensions import Self
class QueryBuilder:
def where(self, condition: str) -> Self:
self._conditions.append(condition)
return self
def limit(self, n: int) -> Self:
self._limit = n
return self
override (PEP 698, stdlib in 3.12)
Catches typos when overriding parent methods:
from typing_extensions import override
class Animal:
def speak(self) -> str:
return "..."
class Dog(Animal):
@override
def speak(self) -> str: # OK
return "Woof"
@override
def spek(self) -> str: # Type checker error!
return "Woof"
TypeIs (PEP 742, stdlib in 3.13)
A safer version of TypeGuard that narrows in both branches:
from typing_extensions import TypeIs
def is_str(val: object) -> TypeIs[str]:
return isinstance(val, str)
def process(val: int | str):
if is_str(val):
val.upper() # Type checker knows: str
else:
val + 1 # Type checker knows: int
ReadOnly for TypedDict (PEP 705, stdlib in 3.13)
Mark specific fields as immutable:
from typing_extensions import TypedDict, ReadOnly
class Config(TypedDict):
name: ReadOnly[str] # Cannot be modified
debug: bool # Can be modified
Unpack for **kwargs (PEP 692, stdlib in 3.12)
Type individual keyword arguments:
from typing_extensions import TypedDict, Unpack
class RequestOptions(TypedDict, total=False):
timeout: int
headers: dict[str, str]
verify: bool
def fetch(url: str, **kwargs: Unpack[RequestOptions]) -> str: ...
When to use typing-extensions vs. typing
| Situation | Use |
|---|---|
| Single Python version (latest) | typing directly |
| Library supporting multiple versions | typing_extensions always |
| Application pinned to one version | typing for available features, typing_extensions for newer ones |
| New project with no constraints | typing_extensions — it’s simpler than conditional imports |
Package characteristics
- Zero dependencies — pure Python, no transitive requirements
- Frequently updated — new release within weeks of each CPython beta
- Tiny — less than 200KB installed
- 700M+ monthly downloads — the 5th most downloaded package on PyPI
- Maintained by CPython core developers — Alex Grönholm, Jelle Zijlstra, and others
How libraries use it in practice
Major libraries like Pydantic, FastAPI, SQLAlchemy, and mypy itself depend on typing-extensions:
# From pydantic's source
from typing_extensions import Annotated, Self, TypedDict, get_type_hints
# From FastAPI's source
from typing_extensions import Annotated, Doc
This is standard practice — even projects with cutting-edge minimum Python versions use typing-extensions for features still in beta.
Common misconception
“typing-extensions is third-party and might diverge from stdlib.” It’s maintained by the same people who maintain typing in CPython. The implementations are either copied directly from CPython or designed to be API-compatible. When you upgrade Python, switching from typing_extensions to typing imports is a no-op change.
The one thing to remember: typing-extensions is the standard way to use modern type hints in production Python — if your project supports more than one Python version, you’re almost certainly using it already.
See Also
- Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.
- Python 311 New Features Python 3.11 made everything faster, error messages smarter, and let you catch several mistakes at once instead of stopping at the first one.
- Python 312 New Features Python 3.12 made type hints shorter, f-strings more powerful, and started preparing Python's engine for a world without the GIL.
- Python 313 New Features Python 3.13 finally lets multiple tasks run at the same time for real, added a speed booster engine, and gave the interactive prompt a colourful makeover.
- Python Exception Groups Python's ExceptionGroup is like getting one report card that lists every mistake at once instead of stopping at the first one.