Skip to content

fix: preserve TypedDict get precision through TypeVar bounds - #22068

Open
mvanhorn wants to merge 1 commit into
python:masterfrom
mvanhorn:fix/16872-typeddict-bound-typevar-get
Open

mvanhorn wants to merge 1 commit into
python:masterfrom
mvanhorn:fix/16872-typeddict-bound-typevar-get

Conversation

@mvanhorn

Copy link
Copy Markdown

In mypy/checkexpr.py, update ExpressionChecker.method_fullname to resolve a TypeVar's proper upper bound for TypedDict method lookup, allowing the existing fallback owner lookup to identify typing.Mapping.get; keep the receiver's original type intact elsewhere and leave unrelated bound kinds unchanged. In mypy/plugins/default.py, normalize the receiver locally in both typed_dict_get_signature_callback and typed_dict_get_callback by inspecting a TypeVar's proper upper bound, then use that local TypedDict type for field lookup, required keys, and closedness. Reuse the existing signature-context and return-type algorithms so empty collection defaults and nested TypedDict defaults work without changing the plugin context contract or adding a helper used only by tests. Calling .get on a TypeVar bounded by a TypedDict loses the field type and produces object, while indexing and direct TypedDict .get preserve the field type. The original example uses a required list[str] field, and the September 2026 confirmation reproduces the issue with both legacy TypeVar declarations and Python 3.12 type parameter syntax. Current direct TypedDict behavior returns the field type alone for required keys, so the original expectation of an unconditional union with None is outdated. The fix should match current direct-receiver behavior, including optional keys, explicit defaults, and contextual inference. Required list[str] key: legacy bounded TypeVar .get returns list[str], matching direct .get and indexing, with and without an explicit default. Returning the original argument as T still preserves generic identity; Optional key (total=False and a mixed Required/NotRequired TypedDict): omitted default returns value-or-None; an unrelated explicit default returns the appropriate union; a default of the field type collapses the union.

Fixes #16872

@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

core (https://github.com/home-assistant/core)
+ homeassistant/data_entry_flow.py:653: error: Unused "type: ignore" comment  [unused-ignore]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Calls to .get on TypeVars bound to TypedDict narrow to object

1 participant