Skip to content

Commit b9d0529

Browse files
authored
Allow class-based TypedDicts in all python versions (#6971)
Entries can't be *declared* in versions that don't support type annotations, of course, but class-based TypedDict still serves a valuable purpose in merging TypedDicts together. This error *only* triggers on empty TypedDicts, since any non-empty ones would have failed earlier with a syntax error. So there is no reason to prohibit it because we can handle that case totally fine.
1 parent 16ade15 commit b9d0529

File tree

3 files changed

+20
-9
lines changed

3 files changed

+20
-9
lines changed

mypy/newsemanal/semanal_typeddict.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,6 @@ def analyze_typeddict_classdef_fields(
120120
* List of types for each key
121121
* Set of required keys
122122
"""
123-
if self.options.python_version < (3, 6):
124-
self.fail('TypedDict class syntax is only supported in Python 3.6', defn)
125-
return [], [], set()
126123
fields = [] # type: List[str]
127124
types = [] # type: List[Type]
128125
for stmt in defn.defs.body:

mypy/semanal_typeddict.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ def check_typeddict_classdef(self, defn: ClassDef,
102102
oldfields: Optional[List[str]] = None) -> Tuple[List[str],
103103
List[Type],
104104
Set[str]]:
105-
if self.options.python_version < (3, 6):
106-
self.fail('TypedDict class syntax is only supported in Python 3.6', defn)
107-
return [], [], set()
108105
fields = [] # type: List[str]
109106
types = [] # type: List[Type]
110107
for stmt in defn.defs.body:

test-data/unit/check-typeddict.test

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,33 @@ reveal_type(p) # E: Revealed type is 'TypedDict('__main__.EmptyDict', {})'
128128
[builtins fixtures/dict.pyi]
129129

130130

131-
-- Define TypedDict (Class syntax errors)
132-
133131
[case testCanCreateTypedDictWithClassOldVersion]
134132
# flags: --python-version 3.5
133+
134+
# Test that we can use class-syntax to merge TypedDicts even in
135+
# versions without type annotations
136+
135137
from mypy_extensions import TypedDict
136138

137-
class Point(TypedDict): # E: TypedDict class syntax is only supported in Python 3.6
139+
MovieBase1 = TypedDict(
140+
'MovieBase1', {'name': str, 'year': int})
141+
MovieBase2 = TypedDict(
142+
'MovieBase2', {'based_on': str}, total=False)
143+
144+
class Movie(MovieBase1, MovieBase2):
138145
pass
146+
147+
def foo(x):
148+
# type: (Movie) -> None
149+
pass
150+
151+
foo({}) # E: Keys ('name', 'year') missing for TypedDict "Movie"
152+
foo({'name': 'lol', 'year': 2009, 'based_on': 0}) # E: Incompatible types (expression has type "int", TypedDict item "based_on" has type "str")
153+
139154
[builtins fixtures/dict.pyi]
140155

156+
-- Define TypedDict (Class syntax errors)
157+
141158
[case testCannotCreateTypedDictWithClassOtherBases]
142159
# flags: --python-version 3.6
143160
from mypy_extensions import TypedDict

0 commit comments

Comments
 (0)