Quickstart guide
This guide will get you type checking Python code with mypy in just a few minutes.
Your first type-checked program
Let’s start with a simple example to see mypy in action.
Create a Python file
Create a file called example.py with the following code: def greeting ( name ):
return 'Hello ' + name
greeting( 'World' ) # This is fine
greeting( 123 ) # This will fail at runtime
Run mypy without type hints
Try running mypy on this file: You’ll see: Success: no issues found in 1 source file
By default, mypy doesn’t check functions without type annotations. This makes it easy to adopt mypy incrementally.
Add type hints
Now let’s add type hints to catch the bug: def greeting ( name : str ) -> str :
return 'Hello ' + name
greeting( 'World' ) # This is fine
greeting( 123 ) # Now mypy will catch this!
Run mypy with type hints
Run mypy again: Now you’ll see an error: example.py:4: error: Argument 1 to "greeting" has incompatible type "int"; expected "str" [arg-type]
Found 1 error in 1 file (checked 1 source file)
Mypy caught the bug without running the code ! This is the power of static type checking.
Understanding type annotations
Type annotations tell mypy (and other readers) what types your code expects:
Function annotations
Variable annotations
Collection types
# The "name: str" says the parameter should be a string
# The "-> str" says the function returns a string
def greeting ( name : str ) -> str :
return 'Hello ' + name
Dynamic vs static typing
Mypy distinguishes between dynamically and statically typed functions:
Dynamically typed (not checked)
Statically typed (checked)
def add ( x , y ):
return x + y
# Mypy won't check this, even though it will fail at runtime
add( "hello" , 123 )
You can control this behavior with flags like --disallow-untyped-defs to require type hints on all functions.
Working with complex types
Mypy supports sophisticated type expressions:
Union types
When a value can be one of several types:
def normalize_id ( user_id : int | str ) -> str :
if isinstance (user_id, int ):
return f 'user- { 100_000 + user_id } '
else :
return user_id
normalize_id( 123 ) # OK: returns 'user-100123'
normalize_id( 'admin' ) # OK: returns 'admin'
Optional types
For values that might be None:
def greet ( name : str | None = None ) -> str :
if name is None :
return "Hello, stranger!"
return f "Hello, { name } !"
greet() # OK: "Hello, stranger!"
greet( "Alice" ) # OK: "Hello, Alice!"
On Python 3.9 and earlier, use Optional[str] instead of str | None, or add from __future__ import annotations at the top of your file.
Generic types
For collections with specific item types:
from collections.abc import Iterable
def greet_all ( names : Iterable[ str ]) -> None :
for name in names:
print ( 'Hello ' + name)
names = [ "Alice" , "Bob" , "Charlie" ]
greet_all(names) # OK
ages = [ 10 , 20 , 30 ]
greet_all(ages) # error: List item 0 has incompatible type "int"; expected "str"
Checking multiple files
Mypy can check entire directories:
Check a single file
Check multiple files
Check a directory recursively
Check a module
Check a package recursively
Real-world example
Here’s a more complete example showing mypy in action:
from dataclasses import dataclass
@dataclass
class User :
name: str
email: str
age: int
def create_user ( name : str , email : str , age : int ) -> User:
if age < 0 :
raise ValueError ( "Age cannot be negative" )
return User( name = name, email = email, age = age)
def send_email ( user : User, message : str ) -> None :
print ( f "Sending to { user.email } : { message } " )
# Usage
user = create_user( "Alice" , "[email protected] " , 30 )
send_email(user, "Welcome!" )
# Mypy catches these errors:
create_user( "Bob" , "[email protected] " , "thirty" ) # error: Argument 3 has incompatible type "str"; expected "int"
send_email( "not a user" , "Hello" ) # error: Argument 1 has incompatible type "str"; expected "User"
Run mypy on this file:
Output:
user.py:19: error: Argument 3 to "create_user" has incompatible type "str"; expected "int" [arg-type]
user.py:20: error: Argument 1 to "send_email" has incompatible type "str"; expected "User" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
Daemon mode for faster checking
For large codebases, use daemon mode for much faster incremental checking:
Start the daemon
The first run will be slow as it builds the cache.
Make changes
Edit your code files.
Re-check (much faster)
Subsequent runs are often sub-second, even for large projects.
Stop the daemon (optional)
Daemon mode can provide 10-50x speedup on incremental checks for large codebases.
Configuration file
For project-specific settings, create a mypy.ini or pyproject.toml file:
[mypy]
python_version = 3.10
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
# Per-module options
[mypy-tests.*]
disallow_untyped_defs = False
Mypy will automatically find and use configuration files in your project directory.
Common flags
Here are some useful command-line flags:
Flag Description --strictEnable all optional checks (recommended for new projects) --disallow-untyped-defsRequire type hints on all functions --ignore-missing-importsSilently ignore imports of untyped libraries --show-error-codesShow error codes in output (helpful for filtering) --prettyUse nicer output with source code snippets --install-typesAutomatically install missing type stubs
Strict mode
Pretty output
Auto-install type stubs
mypy --strict my_project/
Handling third-party libraries
When you import libraries without type hints, mypy will complain:
error: Library stubs not installed for "requests"
note: Hint: "python3 -m pip install types-requests"
You have several options:
Install type stubs
Many popular libraries have separate stub packages: python3 -m pip install types-requests types-PyYAML
Or let mypy install them automatically: mypy --install-types --non-interactive my_project/
Ignore missing imports (per-library)
In your config file: [mypy-requests.*]
ignore_missing_imports = True
Ignore all missing imports (not recommended)
Use the flag (but this reduces type safety): mypy --ignore-missing-imports my_project/
Next steps
Now that you know the basics:
Cheat sheet Quick reference for common type hints and patterns.
Type system reference Deep dive into mypy’s type system features.
Configuration Learn about all configuration options.
Common issues Solutions to frequently encountered problems.