Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 62 additions & 17 deletions peps/pep-0728.rst
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,34 @@ arguments of this type when constructed by calling the class object::
year=2007,
) # Not OK. Extra items not allowed

Interaction with Mapping[KT, VT]
--------------------------------
Supported and Unsupported Operations
------------------------------------

This statement from the `typing spec
<https://typing.python.org/en/latest/spec/typeddict.html#supported-and-unsupported-operations>`__
still holds true.

Operations with arbitrary str keys (instead of string literals or other
expressions with known string values) should generally be rejected.

This means that indexed accesses and assignments with arbitrary keys can still
be rejected even when ``extra_items`` is specified.

Operations that already apply to ``NotRequired`` items should generally also
apply to extra items, following the same rationale from the `typing spec
<https://typing.python.org/en/latest/spec/typeddict.html#supported-and-unsupported-operations>`__
:
Comment thread
PIG208 marked this conversation as resolved.
Outdated

The exact type checking rules are up to each type checker to decide. In some
cases potentially unsafe operations may be accepted if the alternative is to
generate false positive errors for idiomatic code.

Some operations are allowed due to the TypedDict being
:term:`typing:assignable` to ``Mapping[str, VT]`` or ``dict[str, VT]``.
The two following sections will expand on that.

Interaction with Mapping[str, VT]
---------------------------------

A TypedDict type is :term:`typing:assignable` to a type of the form ``Mapping[str, VT]``
when all value types of the items in the TypedDict
Expand Down Expand Up @@ -618,12 +644,12 @@ and ``items()`` on such TypedDict types::
reveal_type(movie.items()) # Revealed type is 'dict_items[str, str]'
reveal_type(movie.values()) # Revealed type is 'dict_values[str, str]'

Interaction with dict[KT, VT]
-----------------------------
Interaction with dict[str, VT]
------------------------------

Because the presence of ``extra_items`` on a closed TypedDict type
prohibits additional required keys in its :term:`typing:structural`
:term:`typing:subtypes <subtype>`, we can determine if the TypedDict type and
:term:`subtypes <subtype>`, we can determine if the TypedDict type and
its structural subtypes will ever have any required key during static analysis.

The TypedDict type is :term:`typing:assignable` to ``dict[str, VT]`` if all
Expand Down Expand Up @@ -708,8 +734,25 @@ been removed in Python 3.13.
Because this is a type-checking feature, it can be made available to older
versions as long as the type checker supports it.

Open Issues
===========
Rejected Ideas
==============

Use ``@final`` instead of ``closed`` Class Parameter
-----------------------------------------------------

This was discussed `here <https://github.com/python/mypy/issues/7981>`__.

Quoting a relevant `comment
<https://github.com/python/mypy/issues/7981#issuecomment-2080161813>`__
from Eric Traut:

The @final class decorator indicates that a class cannot be subclassed. This
makes sense for classes that define nominal types. However, TypedDict is a
structural type, similar to a Protocol. That means two TypedDict classes
with different names but the same field definitions are equivalent types.
Their names and hierarchies don't matter for determining type consistency.
For that reason, @final has no impact on a TypedDict type consistency rules,
nor should it change the behavior of items or values.

Use a Special ``__extra_items__`` Key with the ``closed`` Class Parameter
-------------------------------------------------------------------------
Expand Down Expand Up @@ -767,9 +810,6 @@ types altogether, but there are some disadvantages. `For example
- The types don't appear in an annotation context, so their evaluation will
not be deferred.

Rejected Ideas
==============

Allowing Extra Items without Specifying the Type
------------------------------------------------

Expand Down Expand Up @@ -827,19 +867,24 @@ For example:
[index: string]: number | string
}

This is a known limitation discussed in `TypeScript's issue tracker
<https://github.com/microsoft/TypeScript/issues/17867>`__,
where it is suggested that there should be a way to exclude the defined keys
from the index signature so that it is possible to define a type like
``MovieWithExtraNumber``.
While this restriction allows for sound indexed accesses with arbitrary keys,
it comes with usability limitations discussed in `TypeScript's issue tracker
<https://github.com/microsoft/TypeScript/issues/17867>`__.
A suggestion was to allow excluding the defined keys from the index signature,
to define a type like ``MovieWithExtraNumber``. This probably involves
subtraction types, which is beyond the scope of this PEP.

Reference Implementation
========================

An earlier revision of proposal is supported in `pyright 1.1.352
<https://github.com/microsoft/pyright/releases/tag/1.1.352>`_, and `pyanalyze
This is supported in `pyright 1.1.386
<https://github.com/microsoft/pyright/releases/tag/1.1.386>`_, and an earlier
revision is supported in `pyanalyze
0.12.0 <https://github.com/quora/pyanalyze/releases/tag/v0.12.0>`_.

This is also supported in `typing-extensions 4.13.0rc1
<https://pypi.org/project/typing-extensions/4.13.0rc1/>`_.
Comment thread
PIG208 marked this conversation as resolved.
Outdated

Acknowledgments
===============

Expand Down