Type Hints
- Annotate function signatures with parameter and return types
- Use generic types from
typing:List,Dict,Optional - Validate hints at development time with
mypyor Pyright - Recognize that type hints do not enforce types at runtime
Pydantic, FastAPI, and SQLModel do runtime schema generation directly from typing annotations — a wrong Optional[int] versus int | None can silently change API validation. Staff engineers run mypy --strict in CI and use TypeVar, Protocol, and ParamSpec to type generic decorators without losing signatures.
- Writing
List[int] = []as a default — mutable default trap; useOptional[List[int]] = Noneand init inside. - Confusing
Optional[X]withX = None—Optionalonly marks nullability, it doesn't set the default. - Skipping
from __future__ import annotationson Python <3.10 — forward references andX | Ysyntax break at runtime.
Hints describe what types your functions expect and return. Python doesn't enforce them at runtime — tools like mypy, pyright, and your editor do.
Cheat sheet
x: int,name: str,flag: boollist[int],dict[str, int],tuple[int, str](Python 3.9+)Optional[X]/X | None— nullableCallable[[int, int], int]— function that takes two ints, returns intIterable[X]— anything you canfor ... in
Why bother
- Editor autocomplete catches typos and wrong-type calls
- Self-documenting — type hints often replace half your docstring
- Forces you to think about your interfaces
Try it
- Add type hints to a function you've written.
- What's the difference between
listandlist[int]?
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Write a typed function
add(a: int, b: int) -> intthat returns their sum. Then printadd(3, 4)— expected:7. The checker will verify the annotations are set correctly. - Exercise 2
Write a typed
find_user(users: list[dict], name: str) -> dict | Nonethat returns the first dict whered["name"] == name, orNoneif not found. Test withusers = [{"name": "Ada"}, {"name": "Bob"}]— printfind_user(users, "Bob")(dict) thenfind_user(users, "Zed")(None). - Exercise 3
Use
TypedDictfromtypingto declareSessionwith fieldsuser_id: intandtoken: str. Then write a functionis_valid(s: Session) -> boolthat returnsTruewhentokenis non-empty. Test with a real dict — printis_valid({"user_id": 1, "token": "abc"})andis_valid({"user_id": 2, "token": ""}).