@@ -17,8 +17,8 @@ Abstract
1717:pep: `589 ` defines a :ref: `class-based <typing:typeddict-class-based-syntax >`
1818and a :ref: `functional syntax <typing:typeddict-functional-syntax >` to create
1919typed dictionaries. In both scenarios, it requires defining a class or
20- assigning to a value. In some situations, this can add unnecessary boilerplate,
21- especially if the typed dictionary is only used once.
20+ assigning to a value. In some situations, this can add unnecessary
21+ boilerplate, especially if the typed dictionary is only used once.
2222
2323This PEP proposes the addition of a new inlined syntax, by subscripting the
2424:class: `~typing.TypedDict ` type::
@@ -93,11 +93,15 @@ The :class:`~typing.TypedDict` class is made subscriptable, and accepts a
9393single type argument which must be a :class: `dict `, following the same
9494semantics as the :ref: `functional syntax <typing:typeddict-functional-syntax >`
9595(the dictionary keys are strings representing the field names, and values are
96- valid :ref: `annotation expressions <typing:annotation-expression >`).
96+ valid :ref: `annotation expressions <typing:annotation-expression >`). Only the
97+ comma-separated list of ``key: value `` pairs within braces constructor
98+ (``{k: <type>} ``) is allowed, and should be specified directly as the type
99+ argument (i.e. it is not allowed to use a variable which was previously
100+ assigned a :class: `dict ` instance).
97101
98102Inlined typed dictionaries can be referred to as *anonymous *, meaning they
99- don't have a name. For this reason, their :attr: ` ~type.__name__ ` attribute
100- will be set to an empty string .
103+ don't have a name (see the ` runtime behavior < Runtime behavior >`_
104+ section) .
101105
102106It is possible to define a nested inlined dictionary::
103107
@@ -135,8 +139,6 @@ are bound to some outer scope::
135139
136140 InlinedTD = TypedDict[{'name': T}] # Not OK, `T` refers to a type variable that is not bound to any scope.
137141
138- **TODO ** closed
139-
140142Typing specification changes
141143----------------------------
142144
@@ -158,19 +160,20 @@ implemented as a function at runtime. To be made subscriptable, it will be
158160changed to be a class.
159161
160162Creating an inlined typed dictionary results in a new class, so ``T1 `` and
161- ``T2 `` are the same type (apart from the different :attr: ` ~type.__name__ `) ::
163+ ``T2 `` are of the same type::
162164
163165 from typing import TypedDict
164166
165167 T1 = TypedDict('T1', {'a': int})
166168 T2 = TypedDict[{'a': int}]
167169
170+ As inlined typed dictionaries are are meant to be *anonymous *, their
171+ :attr: `~type.__name__ ` attribute will be set to an empty string.
168172
169173Backwards Compatibility
170174=======================
171175
172- Apart from the :class: `~typing.TypedDict ` internal implementation change, this
173- PEP does not bring any backwards incompatible changes.
176+ This PEP does not bring any backwards incompatible changes.
174177
175178
176179Security Implications
@@ -236,7 +239,7 @@ While this would avoid having to import :class:`~typing.TypedDict` from
236239* For type checkers, :class: `dict ` is a regular class with two type variables.
237240 Allowing :class: `dict ` to be parametrized with a single type argument would
238241 require special casing from type checkers, as there is no way to express
239- parametrization overloads. On ther other hand, :class: `~typing.TypedDict ` is
242+ parametrization overloads. On the other hand, :class: `~typing.TypedDict ` is
240243 already a :term: `special form <typing:special form> `.
241244
242245* If future work extends what inlined typed dictionaries can do, we don't have
@@ -277,6 +280,13 @@ Should we allow the following?::
277280 class SubTD(InlinedTD):
278281 pass
279282
283+ What about defining an inlined typed dictionay extending another typed
284+ dictionary?::
285+
286+ InlinedBase = TypedDict[{'a': int}]
287+
288+ Inlined = TypedDict[InlinedBase, {'b': int}]
289+
280290Using ``typing.Dict `` with a single argument
281291--------------------------------------------
282292
@@ -285,16 +295,39 @@ While using :class:`dict` isn't ideal, we could make use of
285295
286296 def get_movie() -> Dict[{'title': str}]: ...
287297
288- It is less verbose, doesn't have the baggage of :class: `dict `,
289- and is defined as some kind of special form (an alias to the built-in
290- ``dict ``).
298+ It is less verbose, doesn't have the baggage of :class: `dict `, and is
299+ already defined as some kind of special form.
291300
292301However, it is currently marked as deprecated (although not scheduled for
293302removal), so it might be confusing to undeprecate it.
294303
295304This would also set a precedent on typing constructs being parametrizable
296305with a different number of type arguments.
297306
307+ Should inlined typed dictionaries be proper classes?
308+ ----------------------------------------------------
309+
310+ The PEP currently defines inlined typed dictionaries as type objects, to be in
311+ line with the existing syntaxes. To work around the fact that they don't have
312+ a name, their :attr: `~type.__name__ ` attribute is set to an empty string.
313+
314+ This is somewhat arbitrary, and an alternative name could be used as well
315+ (e.g. ``'<TypedDict>' ``).
316+
317+ Alternatively, inlined typed dictionaries could be defined as instances of a
318+ new (internal) typing class, e.g. :class: `!typing._InlinedTypedDict `. While
319+ this solves the naming issue, it requires extra logic in the runtime
320+ implementation to provide the introspection attributes (such as
321+ :attr: `~typing.TypedDict.__total__ `), and tools relying on runtime
322+ introspection would have to add proper support for this new type.
323+
324+ Inlined typed dictionaries and extra items
325+ ------------------------------------------
326+
327+ :pep: `728 ` introduces the concept of *closed * type dictionaries. Inlined
328+ typed dictionaries should probably be implicitly *closed *, but it may be
329+ better to wait for :pep: `728 ` to be accepted first.
330+
298331
299332Copyright
300333=========
0 commit comments