Merged via Meta CodeSyncCorrectnessMerged Jun 23, 2026
Fix TypedDict literal defaults for get/pop
Fixed Pyrefly's TypedDict method synthesis so literal defaults passed to get/pop preserve the field's precise type when the default is already assignable to that field.
facebook/pyrefly · #3831
Problem
For a non-required TypedDict field typed as a Literal union, data.get("key", "value2") could resolve to Literal["value1", "value2"] | str. The default literal was flowing through the generic default overload, widening an already-valid field default into a less precise string type.
Approach
Added a field-typed default overload before the generic default overload when synthesizing TypedDict get/pop methods, so defaults assignable to the field type return the field type while incompatible defaults keep the existing FieldType | T behavior.
Impact and scope
- Improves Pyrefly's type precision for Python code that uses NotRequired TypedDict fields with literal defaults.
- Reduces false-positive type widening in common config, state, and structured-dictionary access patterns.
- Preserves existing fallback behavior for defaults outside the field type by keeping the generic overload after the precise overload.
Validation
- Added test_get_not_required_literal_default with assert_type coverage for NotRequired[Literal[...]] and a literal default.
- PR validation covered cargo fmt plus focused Pyrefly tests for the new regression, get behavior, and pop behavior.
- Landed as Meta CodeSync commit b2f67a7 with author goutamadwant and PR #3831 referenced in the public commit message.