@@ -1469,9 +1469,6 @@ These are not used in annotations. They are building blocks for declaring types.
1469
1469
1470
1470
assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
1471
1471
1472
- The type info for introspection can be accessed via ``Point2D.__annotations__ ``,
1473
- ``Point2D.__total__ ``, ``Point2D.__required_keys__ ``, and
1474
- ``Point2D.__optional_keys__ ``.
1475
1472
To allow using this feature with older versions of Python that do not
1476
1473
support :pep: `526 `, ``TypedDict `` supports two additional equivalent
1477
1474
syntactic forms:
@@ -1488,6 +1485,18 @@ These are not used in annotations. They are building blocks for declaring types.
1488
1485
The keyword-argument syntax is deprecated in 3.11 and will be removed
1489
1486
in 3.13. It may also be unsupported by static type checkers.
1490
1487
1488
+ The functional syntax should also be used when any of the keys are not valid
1489
+ :ref: `identifiers `, for example because they are keywords or contain hyphens.
1490
+ Example::
1491
+
1492
+ # raises SyntaxError
1493
+ class Point2D(TypedDict):
1494
+ in: int # 'in' is a keyword
1495
+ x-y: int # name with hyphens
1496
+
1497
+ # OK, functional syntax
1498
+ Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
1499
+
1491
1500
By default, all keys must be present in a ``TypedDict ``. It is possible to
1492
1501
override this by specifying totality.
1493
1502
Usage::
@@ -1504,6 +1513,82 @@ These are not used in annotations. They are building blocks for declaring types.
1504
1513
``True `` as the value of the ``total `` argument. ``True `` is the default,
1505
1514
and makes all items defined in the class body required.
1506
1515
1516
+ It is possible for a ``TypedDict `` type to inherit from one or more other ``TypedDict `` types
1517
+ using the class-based syntax.
1518
+ Usage::
1519
+
1520
+ class Point3D(Point2D):
1521
+ z: int
1522
+
1523
+ ``Point3D `` has three items: ``x ``, ``y `` and ``z ``. It is equivalent to this
1524
+ definition::
1525
+
1526
+ class Point3D(TypedDict):
1527
+ x: int
1528
+ y: int
1529
+ z: int
1530
+
1531
+ A ``TypedDict `` cannot inherit from a non-TypedDict class,
1532
+ notably including :class: `Generic `. For example::
1533
+
1534
+ class X(TypedDict):
1535
+ x: int
1536
+
1537
+ class Y(TypedDict):
1538
+ y: int
1539
+
1540
+ class Z(object): pass # A non-TypedDict class
1541
+
1542
+ class XY(X, Y): pass # OK
1543
+
1544
+ class XZ(X, Z): pass # raises TypeError
1545
+
1546
+ T = TypeVar('T')
1547
+ class XT(X, Generic[T]): pass # raises TypeError
1548
+
1549
+ A ``TypedDict `` can be introspected via annotations dicts
1550
+ (see :ref: `annotations-howto ` for more information on annotations best practices),
1551
+ :attr: `__total__ `, :attr: `__required_keys__ `, and :attr: `__optional_keys__ `.
1552
+
1553
+ .. attribute :: __total__
1554
+
1555
+ ``Point2D.__total__ `` gives the value of the ``total `` argument.
1556
+ Example::
1557
+
1558
+ >>> from typing import TypedDict
1559
+ >>> class Point2D(TypedDict): pass
1560
+ >>> Point2D.__total__
1561
+ True
1562
+ >>> class Point2D(TypedDict, total=False): pass
1563
+ >>> Point2D.__total__
1564
+ False
1565
+ >>> class Point3D(Point2D): pass
1566
+ >>> Point3D.__total__
1567
+ True
1568
+
1569
+ .. attribute :: __required_keys__
1570
+ .. attribute :: __optional_keys__
1571
+
1572
+ ``Point2D.__required_keys__ `` and ``Point2D.__optional_keys__ `` return
1573
+ :class: `frozenset ` objects containing required and non-required keys, respectively.
1574
+ Currently the only way to declare both required and non-required keys in the
1575
+ same ``TypedDict `` is mixed inheritance, declaring a ``TypedDict `` with one value
1576
+ for the ``total `` argument and then inheriting it from another ``TypedDict `` with
1577
+ a different value for ``total ``.
1578
+ Usage::
1579
+
1580
+ >>> class Point2D(TypedDict, total=False):
1581
+ ... x: int
1582
+ ... y: int
1583
+ ...
1584
+ >>> class Point3D(Point2D):
1585
+ ... z: int
1586
+ ...
1587
+ >>> Point3D.__required_keys__ == frozenset({'z'})
1588
+ True
1589
+ >>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
1590
+ True
1591
+
1507
1592
See :pep: `589 ` for more examples and detailed rules of using ``TypedDict ``.
1508
1593
1509
1594
.. versionadded :: 3.8
0 commit comments