Question presented to candidate:
"You have a match over an order-status enum. Next month someone adds a new status. How do you make sure every match that should handle it gets flagged, instead of silently doing nothing?"
What a strong answer should cover:
- Python does not check exhaustiveness at runtime: when no case matches, the
matchdoes nothing and a function falls off the end returningNone. - The runtime safety net: a final
case _:that raises;typing.assert_never(x)(3.11+) does that and also raisesAssertionErroreven underpython -O. - The static check: with
assert_never(x)in the default branch, mypy and pyright narrowxcase by case and report the leftover type (for exampleLiteral[Status.REFUNDED]) when a case is missing. - Checkers can also flag a missing case without
assert_never: mypy's opt-in--enable-error-code exhaustive-match(mypy 1.17+) and pyright'sreportMatchNotExhaustive(on in strict mode). - It only works over closed types: enums,
Literal[...],bool, and unions of classes. A bareobject,strorintcan never be exhausted. - A test that iterates
Enummembers ortyping.get_args(Union)catches gaps in projects without a checker in CI.
Clarifying questions expected:
- Does the project run mypy or pyright in CI, and in which mode?
- Is the value a closed set (enum, Literal, union of classes), or arbitrary input that needs a real default?
Code / implementation expected: Yes β a match ending in case _: assert_never(x) plus the checker error it produces.