Question presented to candidate:
"Say a function takes a bunch of optional settings through **kwargs β timeout, retries, verbose. How would you type that so a checker catches a misspelled keyword or a wrong value type? What do TypedDict and Unpack each contribute, and what happens at runtime?"
What a strong answer should cover:
- The old form
**kwargs: inttypes every value the same; it cannot give each keyword its own name and type, and inside the functionkwargsisdict[str, int]. **kwargs: Unpack[SomeTypedDict](PEP 692, Python 3.12;typing_extensionsbefore that, andtyping.Unpackitself exists from 3.11) tells the checker the function accepts exactly those keyword names, each with its own type.total=False,Required[...]andNotRequired[...](PEP 655, 3.11) decide which keywords are mandatory; required keys become required keyword arguments, the rest optional.- Checkers report unknown names, wrong types, missing required keys and a named parameter that overlaps a TypedDict key; inside the function
kwargshas the TypedDict type. - Nothing is checked at runtime: the annotation is metadata,
kwargsis a plaindict, and a typo still runs. Validate at the boundary if the input is untrusted. - Trade-off against explicit keyword-only parameters: Unpack shines when the same option set is shared by several functions or wrappers that forward
**kwargs.
Clarifying questions expected:
- Which Python version and type checker does the codebase use (3.12+
typing.Unpacksupport, ortyping_extensions)? - Do the options come from Python callers only, or also from untrusted data that needs runtime validation?
Code / implementation expected: Yes β a TypedDict, a function using **kwargs: Unpack[...], and the checker errors it produces.