Repository navigation
Report missing required TypedDict keys when unpacking a TypedDict - #5407
akhil9tiet wants to merge 10 commits into
Conversation
Add test cases for TypedDict unpacking with missing required keys.
|
This pull request has been imported. If you are a Meta employee, you can view this in D127732579. (Because this pull request was imported automatically, there will not be any future comments.) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The new missing-required-key diagnostic also fires when unpacking a TypedDict whose required keys don't cover the target's.
This comment has been minimized.
This comment has been minimized.
stroxler
left a comment
There was a problem hiding this comment.
Thanks!
Based on AI review, I think there's one issue we should address before merge:
Anonymous TypedDict fields aren’t counted as present
pyrefly/pyrefly/lib/alt/class/typed_dict.rs
Lines 185 to 194 in 658d0cf
Type::TypedDict(unpacked) matches both declared and anonymous TypedDicts. Pyrefly infers ordinary dictionary literals as anonymous TypedDicts with required: false on every field. The new loop therefore adds no keys, but leaves has_unknown_expansion false.
Source tracing indicates this now reports a missing x:
from typing import TypedDict
class Target(TypedDict):
x: int
def f() -> Target:
source = {"x": 1}
return {**source} # Newly reports missing required key `x`Smallest fix: restrict required-field counting to TypedDict::TypedDict, preserving the unknown-expansion fallback for anonymous TypedDicts. Add the example above as a regression test.
The declared-TypedDict behavior otherwise looks correct, and the change is appropriately localized. I’d also add a NotRequired source-field test to protect the distinction between declared optional fields and inferred dictionary entries.
This comment has been minimized.
This comment has been minimized.
|
Fixed — the required-field counting in the unpack arm is now restricted to declared |
This comment has been minimized.
This comment has been minimized.
Fix missing required key error in TypedDict conversion.
This comment has been minimized.
This comment has been minimized.
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Fixes #5405
AnswersSolver::check_dict_items_against_typed_dict skips the missing-required-key check whenever has_expansion is true; when a TypedDict is unpacked its required keys should count as present, skipping only for unknown-key types like plain dict.
In check_dict_items_against_typed_dict, the blanket has_expansion flag is replaced with has_unknown_expansion: when an unpacked value is a TypedDict, its required keys are added to the known keys set, so a missing required key is still reported; the check is skipped only when unpacking a type whose keys are unknown, such as a plain dict. Added test_typed_dict_unpacking_missing_required_key, which unpacks an open TypedDict and a closed TypedDict into Target (both missing y) and includes the positive case of unpacking Target itself.