@@ -1153,3 +1153,192 @@ demonstrates how to work with coroutines. One version
1153
1153
`uses async/await <https://github.com/python/mypy/blob/master/test-data/samples/crawl2.py >`_
1154
1154
and one
1155
1155
`uses yield from <https://github.com/python/mypy/blob/master/test-data/samples/crawl.py >`_.
1156
+
1157
+ TypedDict
1158
+ *********
1159
+
1160
+ Python programs often use dictionaries with string keys to represent objects.
1161
+ Here is a typical example:
1162
+
1163
+ .. code-block :: python
1164
+
1165
+ movie = {' name' : ' Blade Runner
5279
' , ' year' : 1982 }
1166
+
1167
+ Only a fixed set of string keys is expected (``'name' `` and
1168
+ ``'year' `` above), and each key has an independent value type (``str ``
1169
+ for ``'name' `` and ``int `` for ``'year' `` above). We've previously
1170
+ seen the ``Dict[K, V] `` type, which lets you declare uniform
1171
+ dictionary types, where every value has the same type, and arbitrary keys
1172
+ are supported. This is clearly not a good fit for
1173
+ ``movie `` above. Instead, you can use a ``TypedDict `` to give a precise
1174
+ type for objects like ``movie ``, where the type of each
1175
+ dictionary value depends on the key:
1176
+
1177
+ .. code-block :: python
1178
+
1179
+ from mypy_extensions import TypedDict
1180
+
1181
+ Movie = TypedDict(' Movie' , {' name' : str , ' year' : int })
1182
+
1183
+ movie = {' name' : ' Blade Runner' , ' year' : 1982 } # type: Movie
1184
+
1185
+ ``Movie `` is a TypedDict type with two items: ``'name' `` (with type ``str ``)
1186
+ and ``'year' `` (with type ``int ``). Note that we used an explicit type
1187
+ annotation for the ``movie `` variable. This type annotation is
1188
+ important -- without it, mypy will try to infer a regular, uniform
1189
+ ``Dict `` type for ``movie ``, which is not what we want here.
1190
+
1191
+ .. note ::
1192
+
1193
+ If you pass a TypedDict object as an argument to a function, no
1194
+ type annotation is usually necessary since mypy can infer the
1195
+ desired type based on the declared argument type. Also, if an
1196
+ assignment target has been previously defined, and it has a
1197
+ TypedDict type, mypy will treat the assigned value as a TypedDict,
1198
+ not ``Dict ``.
1199
+
1200
+ Now mypy will recognize these as valid:
1201
+
1202
+ .. code-block :: python
1203
+
1204
+ name = movie[' name' ] # Okay; type of name is str
1205
+ year = movie[' year' ] # Okay; type of year is int
1206
+
1207
+ Mypy will detect an invalid key as an error:
1208
+
1209
+ .. code-block :: python
1210
+
1211
+ director = movie[' director' ] # Error: 'director' is not a valid key
1212
+
1213
+ Mypy will also reject a runtime-computed expression as a key, as
1214
+ it can't verify that it's a valid key. You can only use string
1215
+ literals as TypedDict keys.
1216
+
1217
+ The ``TypedDict `` type object can also act as a constructor. It
1218
+ returns a normal ``dict `` object at runtime -- a ``TypedDict `` does
1219
+ not define a new runtime type:
1220
+
1221
+ .. code-block :: python
1222
+
1223
+ toy_story = Movie(name = ' Toy Story' , year = 1995 )
1224
+
1225
+ This is equivalent to just constructing a dictionary directly using
1226
+ ``{ ... } `` or ``dict(key=value, ...) ``. The constructor form is
1227
+ sometimes convenient, since it can be used without a type annotation,
1228
+ and it also makes the type of the object explicit.
1229
+
1230
+ Like all types, TypedDicts can be used as components to build
1231
+ arbitrarily complex types. For example, you can define nested
1232
+ TypedDicts and containers with TypedDict items.
1233
+ Unlike most other types, mypy uses structural compatibility checking
1234
+ (or structural subtyping) with TypedDicts. A TypedDict object with
1235
+ extra items is compatible with a narrower TypedDict, assuming item
1236
+ types are compatible (*totality * also affects
1237
+ subtyping, as discussed below).
1238
+
1239
+ .. note ::
1240
+
1241
+ You need to install ``mypy_extensions `` using pip to use ``TypedDict ``:
1242
+
1243
+ .. code-block :: text
1244
+
1245
+ python3 -m pip install --upgrade mypy-extensions
1246
+
1247
+ Or, if you are using Python 2:
1248
+
1249
+ .. code-block :: text
1250
+
1251
+ pip install --upgrade mypy-extensions
1252
+
1253
+ .. note ::
1254
+
1255
+ TypedDict is experimental. Details of TypedDict may change in
1256
+ future mypy releases.
1257
+
1258
+ Totality
1259
+ --------
1260
+
1261
+ By default mypy ensures that a TypedDict object has all the specified
1262
+ keys. This will be flagged as an error:
1263
+
1264
+ .. code-block :: python
1265
+
1266
+ # Error: 'year' missing
1267
+ toy_story = {' name' : ' Toy Story' } # type: Movie
1268
+
1269
+ Sometimes you want to allow keys to be left out when creating a
1270
+ TypedDict object. You can provide the ``total=False `` argument to
1271
+ ``TypedDict(...) `` to achieve this:
1272
+
1273
+ .. code-block :: python
1274
+
1275
+ GuiOptions = TypedDict(
1276
+ ' GuiOptions' , {' language' : str , ' color' : str }, total = False )
1277
+ options = {} # type: GuiOptions # Okay
1278
+ options[' language' ] = ' en'
1279
+
1280
+ You may need to use ``get() `` to access items of a partial (non-total)
1281
+ TypedDict, since indexing using ``[] `` could fail at runtime.
1282
+ However, mypy still lets use ``[] `` with a partial TypedDict -- you
1283
+ just need to be careful with it, as it could result in a ``KeyError ``.
1284
+ Requiring ``get() `` everywhere would be too cumbersome. (Note that you
1285
+ are free to use ``get() `` with total TypedDicts as well.)
1286
+
1287
+ Totality also affects structural compatibility. You can't use a partial
1288
+ TypedDict when a total one is expected. Also, a total typed dict is not
1289
+ valid when a partial one is expected.
1290
+
1291
+ Class-based syntax
1292
+ ------------------
1293
+
1294
+ Python 3.6 supports an alternative, class-based syntax to define a
1295
+ TypedDict:
1296
+
1297
+ .. code-block :: python
1298
+
1299
+ from mypy_extensions import TypedDict
1300
+
1301
+ class Movie (TypedDict ):
1302
+ name: str
1303
+ year: int
1304
+
1305
+ The above definition is equivalent to the original ``Movie ``
1306
+ definition. It doesn't actually define a real class. This syntax also
1307
+ supports a form of inheritance -- subclasses can define additional
1308
+ items. However, this is primarily a notational shortcut. Since mypy
1309
+ uses structural compatibility with TypedDicts, inheritance is not
1310
+ required for compatibility. Here is an example of inheritance:
1311
+
1312
+ .. code-block :: python
1313
+
1314
+ class Movie (TypedDict ):
1315
+ name: str
1316
+ year: int
1317
+
1318
+ class BookBasedMovie (Movie ):
1319
+ based_on: str
1320
+
1321
+ Now ``BookBasedMovie `` has keys ``name ``, ``year `` and ``based_on ``.
1322
+
1323
+ Mixing required and non-required items
1324
+ --------------------------------------
1325
+
1326
+ In addition to allowing reuse across TypedDict types, inheritance also allows
1327
+ you to mix required and non-required (using ``total=False ``) items
1328
+ in a single TypedDict. Example:
1329
+
1330
+ .. code-block :: python
1331
+
1332
+ class MovieBase (TypedDict ):
1333
+ name: str
1334
+ year: int
1335
+
1336
+ class Movie (MovieBase , total = False ):
1337
+ based_on: str
1338
+
1339
+ Now ``Movie `` has required keys ``name `` and ``year ``, while ``based_on ``
1340
+ can be left out when constructing an object. A TypedDict with a mix of required
1341
+ and non-required keys, such as ``Movie `` above, will only be compatible with
1342
+ another TypedDict if all required keys in the other TypedDict are required keys in the
1343
+ first TypedDict, and all non-required keys of the other TypedDict are also non-required keys
1344
+ in the first TypedDict.
0 commit comments