Skip to content

Commit d28b396

Browse files
authored
Fix indexed assignment check when TypedDict is used as upper bound (#8621)
Fixes #8576
1 parent 20bc0b4 commit d28b396

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

mypy/checker.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,8 +3049,15 @@ def check_indexed_assignment(self, lvalue: IndexExpr,
30493049
"""
30503050
self.try_infer_partial_type_from_indexed_assignment(lvalue, rvalue)
30513051
basetype = get_proper_type(self.expr_checker.accept(lvalue.base))
3052-
if isinstance(basetype, TypedDictType):
3053-
item_type = self.expr_checker.visit_typeddict_index_expr(basetype, lvalue.index)
3052+
if (isinstance(basetype, TypedDictType) or (isinstance(basetype, TypeVarType)
3053+
and isinstance(get_proper_type(basetype.upper_bound), TypedDictType))):
3054+
if isinstance(basetype, TypedDictType):
3055+
typed_dict_type = basetype
3056+
else:
3057+
upper_bound_type = get_proper_type(basetype.upper_bound)
3058+
assert isinstance(upper_bound_type, TypedDictType)
3059+
typed_dict_type = upper_bound_type
3060+
item_type = self.expr_checker.visit_typeddict_index_expr(typed_dict_type, lvalue.index)
30543061
method_type = CallableType(
30553062
arg_types=[self.named_type('builtins.str'), item_type],
30563063
arg_kinds=[ARG_POS, ARG_POS],

test-data/unit/check-typeddict.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,3 +2022,23 @@ class A:
20222022
reveal_type(A().b) # N: Revealed type is 'Any'
20232023
[builtins fixtures/dict.pyi]
20242024
[typing fixtures/typing-typeddict.pyi]
2025+
2026+
[case testTypedDictAsUpperBoundAndIndexedAssign]
2027+
from typing import TypeVar, Generic, TypedDict
2028+
2029+
2030+
class BaseDict(TypedDict, total=False):
2031+
foo: int
2032+
2033+
2034+
_DICT_T = TypeVar('_DICT_T', bound=BaseDict)
2035+
2036+
2037+
class SomeGeneric(Generic[_DICT_T]):
2038+
def __init__(self, data: _DICT_T) -> None:
2039+
self._data: _DICT_T = data
2040+
2041+
def set_state(self) -> None:
2042+
self._data['foo'] = 1
2043+
[builtins fixtures/dict.pyi]
2044+
[typing fixtures/typing-typeddict.pyi]

0 commit comments

Comments
 (0)