Type Hints Explained¶
Type hints tell Python (and your editor) what kind of data a variable or function expects. They do not change how your code runs — Python ignores them at runtime. But they help you catch mistakes before you run anything.
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize |
|---|---|---|---|---|---|
| You are here | Projects | Videos | Quiz | Flashcards | Diagrams |
Why type hints matter¶
Without type hints, you have to remember what every function expects:
def greet(name, times):
for i in range(times):
print(f"Hello, {name}!")
greet("Alice", "3") # Bug! "3" is a string, not an int — crashes at runtime
With type hints, your editor warns you immediately:
def greet(name: str, times: int) -> None:
for i in range(times):
print(f"Hello, {name}!")
greet("Alice", "3") # Editor underlines "3" — wrong type
Basic syntax¶
Variable annotations¶
Function annotations¶
def add(a: int, b: int) -> int:
return a + b
def say_hello(name: str) -> None:
print(f"Hello, {name}")
The -> int means "this function returns an integer." -> None means it returns nothing.
Collections¶
# A list of strings
names: list[str] = ["Alice", "Bob", "Charlie"]
# A dictionary mapping strings to integers
scores: dict[str, int] = {"Alice": 95, "Bob": 87}
# A set of integers
unique_ids: set[int] = {1, 2, 3}
# A tuple with specific types
point: tuple[float, float] = (3.14, 2.71)
Optional values¶
When a value might be None, use | None (Python 3.10+) or Optional:
# Python 3.10+ (preferred)
def find_user(user_id: int) -> dict | None:
if user_id in database:
return database[user_id]
return None
# Older Python (still works everywhere)
from typing import Optional
def find_user(user_id: int) -> Optional[dict]:
if user_id in database:
return database[user_id]
return None
Union types¶
When a value can be one of several types:
# Python 3.10+
def display(value: str | int | float) -> str:
return str(value)
# Older Python
from typing import Union
def display(value: Union[str, int, float]) -> str:
return str(value)
Type aliases¶
Create shortcuts for complex types:
# Instead of repeating dict[str, list[int]] everywhere:
StudentScores = dict[str, list[int]]
def get_top_students(scores: StudentScores) -> list[str]:
return [name for name, vals in scores.items() if max(vals) > 90]
Generics with TypeVar¶
When you want a function to work with any type but keep types consistent:
from typing import TypeVar
T = TypeVar("T")
def first_item(items: list[T]) -> T:
return items[0]
# Python infers the type:
name = first_item(["Alice", "Bob"]) # name is str
number = first_item([1, 2, 3]) # number is int
Protocol — structural typing¶
A Protocol defines what methods an object must have, without requiring inheritance:
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> str: ...
class Circle:
def draw(self) -> str:
return "Drawing a circle"
class Square:
def draw(self) -> str:
return "Drawing a square"
def render(shape: Drawable) -> None:
print(shape.draw())
# Both work — they have a draw() method
render(Circle())
render(Square())
Neither Circle nor Square inherits from Drawable. They just happen to have a draw() method, and that is enough.
Running a type checker¶
Type hints are enforced by external tools, not Python itself:
Your editor (VS Code with Pylance) checks types automatically as you type.
Common mistakes¶
Forgetting return type:
def greet(name: str): # What does this return? Unclear.
return f"Hello, {name}"
def greet(name: str) -> str: # Clear: returns a string.
return f"Hello, {name}"
Using list instead of list[str]:
def process(items: list): # A list of what? Not helpful.
...
def process(items: list[str]): # A list of strings. Much better.
...
Confusing Optional[X] with X:
def find(name: str) -> Optional[str]:
...
result = find("Alice")
print(result.upper()) # Bug! result might be None
# Fix: check first
if result is not None:
print(result.upper())
When type hints are introduced in this curriculum¶
- Level 00: No type hints (focus on basics)
- Level 1: Basic function annotations (
def greet(name: str) -> str) - Level 2: Collection types (
list[str],dict[str, int]) - Level 3+: Optional, Union, TypeVar, Protocol
You do not need to learn all of this at once. Come back to this page as you level up.
Practice¶
Quick check: Take the quiz
Review: Flashcard decks Practice reps: Coding challenges
| ← Prev | Home | Next → |
|---|---|---|