@@ -128,6 +128,9 @@ Person({"name": "Alice"})
128
128
accepts_person({" name" : " Alice" })
129
129
# TODO : this should be an error, similar to the above
130
130
house.owner = {" name" : " Alice" }
131
+ a_person: Person
132
+ # TODO : this should be an error, similar to the above
133
+ a_person = {" name" : " Alice" }
131
134
```
132
135
133
136
All of these have an invalid type for the ` name ` field:
@@ -144,6 +147,9 @@ Person({"name": None, "age": 30})
144
147
accepts_person({" name" : None , " age" : 30 })
145
148
# TODO : this should be an error, similar to the above
146
149
house.owner = {" name" : None , " age" : 30 }
150
+ a_person: Person
151
+ # TODO : this should be an error, similar to the above
152
+ a_person = {" name" : None , " age" : 30 }
147
153
```
148
154
149
155
All of these have an extra field that is not defined in the ` TypedDict ` :
@@ -160,6 +166,9 @@ Person({"name": "Alice", "age": 30, "extra": True})
160
166
accepts_person({" name" : " Alice" , " age" : 30 , " extra" : True })
161
167
# TODO : this should be an error
162
168
house.owner = {" name" : " Alice" , " age" : 30 , " extra" : True }
169
+ # TODO : this should be an error
170
+ a_person: Person
171
+ a_person = {" name" : " Alice" , " age" : 30 , " extra" : True }
163
172
```
164
173
165
174
## Type ignore compatibility issues
@@ -242,8 +251,9 @@ invalid_extra = OptionalPerson(name="George", extra=True)
242
251
243
252
## ` Required ` and ` NotRequired `
244
253
245
- You can have fine-grained control over field requirements using ` Required ` and ` NotRequired `
246
- qualifiers, which override the class-level ` total= ` setting:
254
+ You can have fine-grained control over keys using ` Required ` and ` NotRequired ` qualifiers. These
255
+ qualifiers override the class-level ` total ` setting, which sets the default (` total=True ` means that
256
+ all keys are required by default, ` total=False ` means that all keys are non-required by default):
247
257
248
258
``` py
249
259
from typing_extensions import TypedDict, Required, NotRequired
@@ -444,6 +454,12 @@ class Person(TypedDict, total=False):
444
454
id : ReadOnly[Required[int ]]
445
455
name: str
446
456
age: int | None
457
+
458
+ alice: Person = {" id" : 1 , " name" : " Alice" , " age" : 30 }
459
+ alice[" age" ] = 31 # okay
460
+
461
+ # TODO : this should be an error
462
+ alice[" id" ] = 2
447
463
```
448
464
449
465
## Methods on ` TypedDict `
@@ -764,6 +780,38 @@ from typing import TypedDict
764
780
x: TypedDict = {" name" : " Alice" }
765
781
```
766
782
783
+ ### ` dict ` -subclass inhabitants
784
+
785
+ Values that inhabit a ` TypedDict ` type must be instances of ` dict ` itself, not a subclass:
786
+
787
+ ``` py
788
+ from typing import TypedDict
789
+
790
+ class MyDict (dict ):
791
+ pass
792
+
793
+ class Person (TypedDict ):
794
+ name: str
795
+ age: int | None
796
+
797
+ # TODO : this should be an error
798
+ x: Person = MyDict({" name" : " Alice" , " age" : 30 })
799
+ ```
800
+
801
+ ### Cannot be used in ` isinstance ` tests
802
+
803
+ ``` py
804
+ from typing import TypedDict
805
+
806
+ class Person (TypedDict ):
807
+ name: str
808
+ age: int | None
809
+
810
+ def _ (obj : object ) -> bool :
811
+ # TODO : this should be an error
812
+ return isinstance (obj, Person)
813
+ ```
814
+
767
815
## Diagnostics
768
816
769
817
<!-- snapshot-diagnostics -->
0 commit comments