What is PEP 484?
PEP 484: Type Hints is the 2014 proposal that gave Python optional static types. Accepted for Python 3.5, it defines what annotations like name: str mean, introduces the typing module, and establishes the gradual-typing model that every Python type checker implements.
The PEP was co-authored by Guido van Rossum and Jukka Lehtosalo, who created mypy. Type hints grew out of mypy’s annotation syntax, then became a language standard that other tools could build on.
What do type hints do at runtime? Nothing
Python stores annotations but never enforces them. This program runs without complaint:
def greet(name: str) -> str:
return f"hello {name}"
greet(42) # runs fine and returns "hello 42"The annotations only matter to tools that read them: a type checker like mypy, Pyright, or ty flags greet(42) as an error without running the code, and editors use the same information for completion and inline documentation.
That separation is the core design decision of PEP 484. The interpreter’s behavior never changes; correctness checking happens in a separate tool, at whatever strictness you choose.
Why does “gradual” matter?
PEP 484 specifies gradual typing: annotated and unannotated code coexist in one program. Unannotated values default to Any, a type compatible with everything, so a checker stays quiet about code you haven’t annotated yet.
This is what makes type hints adoptable in an existing codebase. You can annotate one module, one function, or one parameter at a time, and the checker validates exactly as much as you’ve declared. How to gradually adopt type checking in an existing Python project walks through that process.
How has the syntax evolved?
PEP 484’s original spelling looks dated in 2026. Later PEPs replaced most of the typing module imports with plain Python syntax:
| PEP 484 original | Modern equivalent | Since |
|---|---|---|
typing.List[int] |
list[int] (PEP 585, builtin generics) |
3.9 |
Union[int, str], Optional[int] |
int | str, int | None (PEP 604, union operator) |
3.10 |
T = TypeVar("T") plus Generic[T] |
class Box[T]: (PEP 695, type parameter syntax) |
3.12 |
| Quoted forward references | Unquoted, evaluated lazily (PEP 649, deferred annotations) | 3.14 |
The gradual-typing semantics underneath are unchanged. A checker written against PEP 484’s model handles all of these spellings.
Which tools implement PEP 484?
Four major type checkers implement the PEP 484 model today: mypy (the original), Pyright (which powers VS Code’s Pylance), ty, and Pyrefly. How do mypy, Pyright, and ty compare? covers choosing between them.
Ruff is not a type checker (Does Ruff support type checking? explains the distinction), but its UP-prefixed rules automatically rewrite PEP 484-era syntax to the modern equivalents in the table.
The typing_extensions package backports new typing constructs to older Python versions, which is how libraries use features like ParamSpec (PEP 612, typed decorators) while still supporting Pythons that predate them.
Learn More
- PEP 484: Type Hints
- The typing specification is the maintained successor to PEP 484’s normative text
- typing module documentation
- What is PEP 561? covers how packages ship their type information
- How to gradually adopt type checking in an existing Python project