Skip to content

Static Type Checking — mypy

When you first learned TypeScript you probably experienced the moment where the compiler caught a real bug before you even ran the code. Python’s type hints give you the same capability — but the interpreter itself never checks them. mypy is the separate static analysis tool that performs that check.

Think of mypy as tsc --noEmit for Python: it reads your annotations and reports type errors without running or compiling anything.

Run this in your terminal:

Terminal window
pip install mypy
# or:
uv add --dev mypy
# Check a single file
mypy src/main.py
# Check entire package
mypy src/
# Strict mode (equivalent to tsconfig "strict: true")
mypy --strict src/
TypeScript
// TypeScript — types enforced by compiler
function greet(name: string): string {
return `Hello, ${name}!`;
}
function add(a: number, b: number): number {
return a + b;
}
// Generic
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
Python
# Python — types checked by mypy, ignored by interpreter
def greet(name: str) -> str:
return f"Hello, {name}!"
def add(a: int, b: int) -> int:
return a + b
# Generic (Python 3.12+ syntax)
def first[T](arr: list[T]) -> T | None:
return arr[0] if arr else None
TypeScript
// TypeScript common types
const names: string[] = ["Alice", "Bob"];
const scores: Map<string, number> = new Map();
const user: { name: string; age: number } | null = null;
// Optional parameter
function find(id: number, strict?: boolean): string | null {
return null;
}
// Union
type Result = { ok: true; value: string } | { ok: false; error: string };
Python
# Python 3.10+ common types
from typing import Optional
names: list[str] = ["Alice", "Bob"]
scores: dict[str, int] = {}
user: dict[str, str | int] | None = None
# Optional parameter (None default = Optional)
def find(id: int, strict: bool = False) -> str | None:
return None
# TypedDict for structured dicts
from typing import TypedDict
class OkResult(TypedDict):
ok: bool
value: str
from typing import Optional
def double(x: int) -> int:
return x * 2
def greet(name: str) -> str:
return f"Hello, {name}!"
# These are fine
print(double(5))
print(greet("Alice"))
# Type hints don't stop this at runtime:
result = double("oops") # mypy would flag this, Python runs it
print(result) # prints 'oopsoops' — string * 2 repeats it!
TypeScript
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"target": "ES2022",
"module": "NodeNext"
}
}
Python
# pyproject.toml [tool.mypy] section
[tool.mypy]
python_version = "3.11"
strict = true # enables all strict checks
warn_return_any = true
disallow_untyped_defs = true
ignore_missing_imports = true # for untyped third-party libs
What is the relationship between Python type hints and the Python interpreter?
Which mypy flag enables all strict checks, similar to "strict: true" in tsconfig.json?
What is the Python 3.10+ syntax for "string or None" as a return type?
mypy is to Python as _____ is to TypeScript.