diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index e9aaee55879a..5104d31f5c26 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -37,6 +37,7 @@ has_placeholder, require_bool_literal_argument, ) +from mypy.state import state from mypy.typeanal import check_for_explicit_any, has_any_from_unimported_type from mypy.types import ( TPDICT_NAMES, @@ -203,7 +204,8 @@ def add_keys_and_types_from_base( any_kind = TypeOfAny.from_error base_args = [AnyType(any_kind) for _ in tvars] - valid_items = self.map_items_to_base(valid_items, tvars, base_args) + with state.strict_optional_set(self.options.strict_optional): + valid_items = self.map_items_to_base(valid_items, tvars, base_args) for key in base_items: if key in keys: self.fail(f'Overwriting TypedDict field "{key}" while merging', ctx) diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 088b52db0473..c1c791304a15 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -3379,3 +3379,20 @@ bar |= d1 # E: Argument 1 to "__ior__" of "TypedDict" has incompatible type "Di bar |= d2 # E: Argument 1 to "__ior__" of "TypedDict" has incompatible type "Dict[int, str]"; expected "TypedDict({'key'?: int, 'value'?: str})" [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict-iror.pyi] + +[case testGenericTypedDictStrictOptionalExtending] +from typing import Generic, TypeVar, TypedDict, Optional + +T = TypeVar("T") +class Foo(TypedDict, Generic[T], total=False): + a: Optional[str] + g: Optional[T] + +class Bar(Foo[T], total=False): + other: str + +b: Bar[int] +reveal_type(b["a"]) # N: Revealed type is "Union[builtins.str, None]" +reveal_type(b["g"]) # N: Revealed type is "Union[builtins.int, None]" +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi]