Typing

A track of P31 · Typing & Robust Code.

Gradual typing that pays for itself: annotations as a contract mypy checks in CI, Optional and | None to force the missing case, and generics, Protocols and ParamSpec for the tricky parts - graded by inspecting the types themselves.

"Python is dynamically typed, so why bother annotating?" is the question every engineer asks once — usually right before an AttributeError: 'NoneType' takes down production. The answer is gradual typing: annotations are optional, cost nothing at runtime, and a checker like mypy reads them to turn a whole class of bugs into a red build on the PR instead of a 2am page.

This track teaches types as a contract you can inspect. You annotate functions and their Optional returns (X | None, which forces the caller to handle the missing case), build a generic Stack[T] so one class is type-safe for any element, meet Protocols — structural "anything with this shape" typing, the duck typing a checker understands — and finally type a decorator with ParamSpec, the piece P29 was missing. Because the browser can't run mypy, every rung grades the annotations by reading them back with typing.get_type_hints — the exact information a type checker consumes — so a function that lies about its types, or forgets them, fails.

It closes with the capstone: take a real, untyped Cart module to a green type contract. Paired with P30's test suite for the same module, that is the discipline's promise made concrete — untested and untyped becomes tested and typed.

Annotations as a contractzero runtime cost, checked by mypyOptional / | Noneforce the missing caseGenerics & Protocolstype-safe containers; structural shapesParamSpectype the P29 decorator
From a single annotation to a whole module that type-checks.