813 lines
72 KiB
HTML
813 lines
72 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta name="color-scheme" content="light dark">
|
|||
|
<title>PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys | peps.python.org</title>
|
|||
|
<link rel="shortcut icon" href="../_static/py.png">
|
|||
|
<link rel="canonical" href="https://peps.python.org/pep-0589/">
|
|||
|
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
|||
|
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
|||
|
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
|||
|
<meta property="og:title" content='PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys | peps.python.org'>
|
|||
|
<meta property="og:description" content="PEP 484 defines the type Dict[K, V] for uniform dictionaries, where each value has the same type, and arbitrary key values are supported. It doesn’t properly support the common pattern where the type of a dictionary value depends on the string value of...">
|
|||
|
<meta property="og:type" content="website">
|
|||
|
<meta property="og:url" content="https://peps.python.org/pep-0589/">
|
|||
|
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
|||
|
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
|||
|
<meta property="og:image:alt" content="Python PEPs">
|
|||
|
<meta property="og:image:width" content="200">
|
|||
|
<meta property="og:image:height" content="200">
|
|||
|
<meta name="description" content="PEP 484 defines the type Dict[K, V] for uniform dictionaries, where each value has the same type, and arbitrary key values are supported. It doesn’t properly support the common pattern where the type of a dictionary value depends on the string value of...">
|
|||
|
<meta name="theme-color" content="#3776ab">
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
|||
|
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Following system colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="9"></circle>
|
|||
|
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected dark colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|||
|
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected light colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="5"></circle>
|
|||
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|||
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|||
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|||
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
</svg>
|
|||
|
<script>
|
|||
|
|
|||
|
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
|||
|
</script>
|
|||
|
<section id="pep-page-section">
|
|||
|
<header>
|
|||
|
<h1>Python Enhancement Proposals</h1>
|
|||
|
<ul class="breadcrumbs">
|
|||
|
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
|||
|
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
|||
|
<li>PEP 589</li>
|
|||
|
</ul>
|
|||
|
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|||
|
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
|||
|
</button>
|
|||
|
</header>
|
|||
|
<article>
|
|||
|
<section id="pep-content">
|
|||
|
<h1 class="page-title">PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys</h1>
|
|||
|
<dl class="rfc2822 field-list simple">
|
|||
|
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">Jukka Lehtosalo <jukka.lehtosalo at iki.fi></dd>
|
|||
|
<dt class="field-even">Sponsor<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">Guido van Rossum <guido at python.org></dd>
|
|||
|
<dt class="field-odd">BDFL-Delegate<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">Guido van Rossum <guido at python.org></dd>
|
|||
|
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/">Typing-SIG list</a></dd>
|
|||
|
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
|||
|
<dt class="field-even">Type<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
|||
|
<dt class="field-odd">Topic<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><a class="reference external" href="../topic/typing/">Typing</a></dd>
|
|||
|
<dt class="field-even">Created<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">20-Mar-2019</dd>
|
|||
|
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">3.8</dd>
|
|||
|
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><p></p></dd>
|
|||
|
<dt class="field-odd">Resolution<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/message/FDO4KFYWYQEP3U2HVVBEBR3SXPHQSHYR/">Typing-SIG message</a></dd>
|
|||
|
</dl>
|
|||
|
<hr class="docutils" />
|
|||
|
<section id="contents">
|
|||
|
<details><summary>Table of Contents</summary><ul class="simple">
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
|||
|
<li><a class="reference internal" href="#class-based-syntax">Class-based Syntax</a></li>
|
|||
|
<li><a class="reference internal" href="#using-typeddict-types">Using TypedDict Types</a></li>
|
|||
|
<li><a class="reference internal" href="#inheritance">Inheritance</a></li>
|
|||
|
<li><a class="reference internal" href="#totality">Totality</a></li>
|
|||
|
<li><a class="reference internal" href="#alternative-syntax">Alternative Syntax</a></li>
|
|||
|
<li><a class="reference internal" href="#type-consistency">Type Consistency</a></li>
|
|||
|
<li><a class="reference internal" href="#supported-and-unsupported-operations">Supported and Unsupported Operations</a></li>
|
|||
|
<li><a class="reference internal" href="#use-of-final-values-and-literal-types">Use of Final Values and Literal Types</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
|
|||
|
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a></li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
</details></section>
|
|||
|
<div class="pep-banner canonical-typing-spec sticky-banner admonition attention">
|
|||
|
<p class="admonition-title">Attention</p>
|
|||
|
<p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/typeddict.html#typeddict" title="(in typing)"><span>TypedDict</span></a> and
|
|||
|
<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.TypedDict" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">typing.TypedDict</span></code></a> for up-to-date specs and documentation. Canonical typing specs are maintained at the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/">typing specs site</a>; runtime typing behaviour is described in the CPython documentation.</p>
|
|||
|
<p class="close-button">×</p>
|
|||
|
<p>See the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/meta.html">typing specification update process</a> for how to propose changes to the typing spec.</p>
|
|||
|
</div>
|
|||
|
<section id="abstract">
|
|||
|
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
|||
|
<p><a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> defines the type <code class="docutils literal notranslate"><span class="pre">Dict[K,</span> <span class="pre">V]</span></code> for uniform
|
|||
|
dictionaries, where each value has the same type, and arbitrary key
|
|||
|
values are supported. It doesn’t properly support the common pattern
|
|||
|
where the type of a dictionary value depends on the string value of
|
|||
|
the key. This PEP proposes a type constructor <code class="docutils literal notranslate"><span class="pre">typing.TypedDict</span></code> to
|
|||
|
support the use case where a dictionary object has a specific set of
|
|||
|
string keys, each with a value of a specific type.</p>
|
|||
|
<p>Here is an example where <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> doesn’t allow us to annotate
|
|||
|
satisfactorily:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span>
|
|||
|
<span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This PEP proposes the addition of a new type constructor, called
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>, to allow the type of <code class="docutils literal notranslate"><span class="pre">movie</span></code> to be represented
|
|||
|
precisely:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypedDict</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Now a type checker should accept this code:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span>
|
|||
|
<span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="motivation">
|
|||
|
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
|||
|
<p>Representing an object or structured data using (potentially nested)
|
|||
|
dictionaries with string keys (instead of a user-defined class) is a
|
|||
|
common pattern in Python programs. Representing JSON objects is
|
|||
|
perhaps the canonical use case, and this is popular enough that Python
|
|||
|
ships with a JSON library. This PEP proposes a way to allow such code
|
|||
|
to be type checked more effectively.</p>
|
|||
|
<p>More generally, representing pure data objects using only Python
|
|||
|
primitive types such as dictionaries, strings and lists has had
|
|||
|
certain appeal. They are easy to serialize and deserialize even
|
|||
|
when not using JSON. They trivially support various useful operations
|
|||
|
with no extra effort, including pretty-printing (through <code class="docutils literal notranslate"><span class="pre">str()</span></code> and
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">pprint</span></code> module), iteration, and equality comparisons.</p>
|
|||
|
<p><a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> doesn’t properly support the use cases mentioned above. Let’s
|
|||
|
consider a dictionary object that has exactly two valid string keys,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">'name'</span></code> with value type <code class="docutils literal notranslate"><span class="pre">str</span></code>, and <code class="docutils literal notranslate"><span class="pre">'year'</span></code> with value type
|
|||
|
<code class="docutils literal notranslate"><span class="pre">int</span></code>. The <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> type <code class="docutils literal notranslate"><span class="pre">Dict[str,</span> <span class="pre">Any]</span></code> would be suitable, but
|
|||
|
it is too lenient, as arbitrary string keys can be used, and arbitrary
|
|||
|
values are valid. Similarly, <code class="docutils literal notranslate"><span class="pre">Dict[str,</span> <span class="pre">Union[str,</span> <span class="pre">int]]</span></code> is too
|
|||
|
general, as the value for key <code class="docutils literal notranslate"><span class="pre">'name'</span></code> could be an <code class="docutils literal notranslate"><span class="pre">int</span></code>, and
|
|||
|
arbitrary string keys are allowed. Also, the type of a subscription
|
|||
|
expression such as <code class="docutils literal notranslate"><span class="pre">d['name']</span></code> (assuming <code class="docutils literal notranslate"><span class="pre">d</span></code> to be a dictionary of
|
|||
|
this type) would be <code class="docutils literal notranslate"><span class="pre">Union[str,</span> <span class="pre">int]</span></code>, which is too wide.</p>
|
|||
|
<p>Dataclasses are a more recent alternative to solve this use case, but
|
|||
|
there is still a lot of existing code that was written before
|
|||
|
dataclasses became available, especially in large existing codebases
|
|||
|
where type hinting and checking has proven to be helpful. Unlike
|
|||
|
dictionary objects, dataclasses don’t directly support JSON
|
|||
|
serialization, though there is a third-party package that implements
|
|||
|
it <a class="footnote-reference brackets" href="#dataclasses-json" id="id1">[1]</a>.</p>
|
|||
|
</section>
|
|||
|
<section id="specification">
|
|||
|
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
|||
|
<p>A TypedDict type represents dictionary objects with a specific set of
|
|||
|
string keys, and with specific value types for each valid key. Each
|
|||
|
string key can be either required (it must be present) or
|
|||
|
non-required (it doesn’t need to exist).</p>
|
|||
|
<p>This PEP proposes two ways of defining TypedDict types. The first uses
|
|||
|
a class-based syntax. The second is an alternative
|
|||
|
assignment-based syntax that is provided for backwards compatibility,
|
|||
|
to allow the feature to be backported to older Python versions. The
|
|||
|
rationale is similar to why <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a> supports a comment-based
|
|||
|
annotation syntax for Python 2.7: type hinting is particularly useful
|
|||
|
for large existing codebases, and these often need to run on older
|
|||
|
Python versions. The two syntax options parallel the syntax variants
|
|||
|
supported by <code class="docutils literal notranslate"><span class="pre">typing.NamedTuple</span></code>. Other proposed features include
|
|||
|
TypedDict inheritance and totality (specifying whether keys are
|
|||
|
required or not).</p>
|
|||
|
<p>This PEP also provides a sketch of how a type checker is expected
|
|||
|
to support type checking operations involving TypedDict objects.
|
|||
|
Similar to <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>, this discussion is left somewhat vague on purpose,
|
|||
|
to allow experimentation with a wide variety of different type
|
|||
|
checking approaches. In particular, type compatibility should be
|
|||
|
based on structural compatibility: a more specific TypedDict type can
|
|||
|
be compatible with a smaller (more general) TypedDict type.</p>
|
|||
|
<section id="class-based-syntax">
|
|||
|
<h3><a class="toc-backref" href="#class-based-syntax" role="doc-backlink">Class-based Syntax</a></h3>
|
|||
|
<p>A TypedDict type can be defined using the class definition syntax with
|
|||
|
<code class="docutils literal notranslate"><span class="pre">typing.TypedDict</span></code> as the sole base class:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypedDict</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">Movie</span></code> is a TypedDict type with two items: <code class="docutils literal notranslate"><span class="pre">'name'</span></code> (with type
|
|||
|
<code class="docutils literal notranslate"><span class="pre">str</span></code>) and <code class="docutils literal notranslate"><span class="pre">'year'</span></code> (with type <code class="docutils literal notranslate"><span class="pre">int</span></code>).</p>
|
|||
|
<p>A type checker should validate that the body of a class-based
|
|||
|
TypedDict definition conforms to the following rules:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>The class body should only contain lines with item definitions of the
|
|||
|
form <code class="docutils literal notranslate"><span class="pre">key:</span> <span class="pre">value_type</span></code>, optionally preceded by a docstring. The
|
|||
|
syntax for item definitions is identical to attribute annotations,
|
|||
|
but there must be no initializer, and the key name actually refers
|
|||
|
to the string value of the key instead of an attribute name.</li>
|
|||
|
<li>Type comments cannot be used with the class-based syntax, for
|
|||
|
consistency with the class-based <code class="docutils literal notranslate"><span class="pre">NamedTuple</span></code> syntax. (Note that
|
|||
|
it would not be sufficient to support type comments for backwards
|
|||
|
compatibility with Python 2.7, since the class definition may have a
|
|||
|
<code class="docutils literal notranslate"><span class="pre">total</span></code> keyword argument, as discussed below, and this isn’t valid
|
|||
|
syntax in Python 2.7.) Instead, this PEP provides an alternative,
|
|||
|
assignment-based syntax for backwards compatibility, discussed in
|
|||
|
<a class="reference internal" href="#alternative-syntax">Alternative Syntax</a>.</li>
|
|||
|
<li>String literal forward references are valid in the value types.</li>
|
|||
|
<li>Methods are not allowed, since the runtime type of a TypedDict
|
|||
|
object will always be just <code class="docutils literal notranslate"><span class="pre">dict</span></code> (it is never a subclass of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">dict</span></code>).</li>
|
|||
|
<li>Specifying a metaclass is not allowed.</li>
|
|||
|
</ul>
|
|||
|
<p>An empty TypedDict can be created by only including <code class="docutils literal notranslate"><span class="pre">pass</span></code> in the
|
|||
|
body (if there is a docstring, <code class="docutils literal notranslate"><span class="pre">pass</span></code> can be omitted):</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">EmptyDict</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="k">pass</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="using-typeddict-types">
|
|||
|
<h3><a class="toc-backref" href="#using-typeddict-types" role="doc-backlink">Using TypedDict Types</a></h3>
|
|||
|
<p>Here is an example of how the type <code class="docutils literal notranslate"><span class="pre">Movie</span></code> can be used:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span>
|
|||
|
<span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>An explicit <code class="docutils literal notranslate"><span class="pre">Movie</span></code> type annotation is generally needed, as
|
|||
|
otherwise an ordinary dictionary type could be assumed by a type
|
|||
|
checker, for backwards compatibility. When a type checker can infer
|
|||
|
that a constructed dictionary object should be a TypedDict, an
|
|||
|
explicit annotation can be omitted. A typical example is a dictionary
|
|||
|
object as a function argument. In this example, a type checker is
|
|||
|
expected to infer that the dictionary argument should be understood as
|
|||
|
a TypedDict:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">record_movie</span><span class="p">(</span><span class="n">movie</span><span class="p">:</span> <span class="n">Movie</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="o">...</span>
|
|||
|
|
|||
|
<span class="n">record_movie</span><span class="p">({</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span> <span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">})</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Another example where a type checker should treat a dictionary display
|
|||
|
as a TypedDict is in an assignment to a variable with a previously
|
|||
|
declared TypedDict type:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie</span><span class="p">:</span> <span class="n">Movie</span>
|
|||
|
<span class="o">...</span>
|
|||
|
<span class="n">movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span> <span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Operations on <code class="docutils literal notranslate"><span class="pre">movie</span></code> can be checked by a static type checker:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie</span><span class="p">[</span><span class="s1">'director'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Ridley Scott'</span> <span class="c1"># Error: invalid key 'director'</span>
|
|||
|
<span class="n">movie</span><span class="p">[</span><span class="s1">'year'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'1982'</span> <span class="c1"># Error: invalid value type ("int" expected)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The code below should be rejected, since <code class="docutils literal notranslate"><span class="pre">'title'</span></code> is not a valid
|
|||
|
key, and the <code class="docutils literal notranslate"><span class="pre">'name'</span></code> key is missing:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">movie2</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'title'</span><span class="p">:</span> <span class="s1">'Blade Runner'</span><span class="p">,</span>
|
|||
|
<span class="s1">'year'</span><span class="p">:</span> <span class="mi">1982</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The created TypedDict type object is not a real class object. Here
|
|||
|
are the only uses of the type a type checker is expected to allow:</p>
|
|||
|
<ul>
|
|||
|
<li>It can be used in type annotations and in any context where an
|
|||
|
arbitrary type hint is valid, such as in type aliases and as the
|
|||
|
target type of a cast.</li>
|
|||
|
<li>It can be used as a callable object with keyword arguments
|
|||
|
corresponding to the TypedDict items. Non-keyword arguments are not
|
|||
|
allowed. Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">m</span> <span class="o">=</span> <span class="n">Movie</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'Blade Runner'</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="mi">1982</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When called, the TypedDict type object returns an ordinary
|
|||
|
dictionary object at runtime:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">m</span><span class="p">))</span> <span class="c1"># <class 'dict'></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>It can be used as a base class, but only when defining a derived
|
|||
|
TypedDict. This is discussed in more detail below.</li>
|
|||
|
</ul>
|
|||
|
<p>In particular, TypedDict type objects cannot be used in
|
|||
|
<code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> tests such as <code class="docutils literal notranslate"><span class="pre">isinstance(d,</span> <span class="pre">Movie)</span></code>. The reason is
|
|||
|
that there is no existing support for checking types of dictionary
|
|||
|
item values, since <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> does not work with many <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>
|
|||
|
types, including common ones like <code class="docutils literal notranslate"><span class="pre">List[str]</span></code>. This would be needed
|
|||
|
for cases like this:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Strings</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">items</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
|
|||
|
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">({</span><span class="s1">'items'</span><span class="p">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">]},</span> <span class="n">Strings</span><span class="p">))</span> <span class="c1"># Should be False</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">({</span><span class="s1">'items'</span><span class="p">:</span> <span class="p">[</span><span class="s1">'x'</span><span class="p">]},</span> <span class="n">Strings</span><span class="p">))</span> <span class="c1"># Should be True</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The above use case is not supported. This is consistent with how
|
|||
|
<code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> is not supported for <code class="docutils literal notranslate"><span class="pre">List[str]</span></code>.</p>
|
|||
|
</section>
|
|||
|
<section id="inheritance">
|
|||
|
<h3><a class="toc-backref" href="#inheritance" role="doc-backlink">Inheritance</a></h3>
|
|||
|
<p>It is possible for a TypedDict type to inherit from one or more
|
|||
|
TypedDict types using the class-based syntax. In this case the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> base class should not be included. Example:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">BookBasedMovie</span><span class="p">(</span><span class="n">Movie</span><span class="p">):</span>
|
|||
|
<span class="n">based_on</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Now <code class="docutils literal notranslate"><span class="pre">BookBasedMovie</span></code> has keys <code class="docutils literal notranslate"><span class="pre">name</span></code>, <code class="docutils literal notranslate"><span class="pre">year</span></code>, and <code class="docutils literal notranslate"><span class="pre">based_on</span></code>.
|
|||
|
It is equivalent to this definition, since TypedDict types use
|
|||
|
structural compatibility:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">BookBasedMovie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
<span class="n">based_on</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Here is an example of multiple inheritance:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">X</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Y</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">y</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">XYZ</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">Y</span><span class="p">):</span>
|
|||
|
<span class="n">z</span><span class="p">:</span> <span class="nb">bool</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The TypedDict <code class="docutils literal notranslate"><span class="pre">XYZ</span></code> has three items: <code class="docutils literal notranslate"><span class="pre">x</span></code> (type <code class="docutils literal notranslate"><span class="pre">int</span></code>), <code class="docutils literal notranslate"><span class="pre">y</span></code>
|
|||
|
(type <code class="docutils literal notranslate"><span class="pre">str</span></code>), and <code class="docutils literal notranslate"><span class="pre">z</span></code> (type <code class="docutils literal notranslate"><span class="pre">bool</span></code>).</p>
|
|||
|
<p>A TypedDict cannot inherit from both a TypedDict type and a
|
|||
|
non-TypedDict base class.</p>
|
|||
|
<p>Additional notes on TypedDict class inheritance:</p>
|
|||
|
<ul>
|
|||
|
<li>Changing a field type of a parent TypedDict class in a subclass is not allowed.
|
|||
|
Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">X</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Y</span><span class="p">(</span><span class="n">X</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="c1"># Type check error: cannot overwrite TypedDict field "x"</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In the example outlined above TypedDict class annotations returns
|
|||
|
type <code class="docutils literal notranslate"><span class="pre">str</span></code> for key <code class="docutils literal notranslate"><span class="pre">x</span></code>:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">Y</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span> <span class="c1"># {'x': <class 'str'>}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>Multiple inheritance does not allow conflict types for the same name field:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">X</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">Y</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">XYZ</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">Y</span><span class="p">):</span> <span class="c1"># Type check error: cannot overwrite TypedDict field "x" while merging</span>
|
|||
|
<span class="n">xyz</span><span class="p">:</span> <span class="nb">bool</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</section>
|
|||
|
<section id="totality">
|
|||
|
<h3><a class="toc-backref" href="#totality" role="doc-backlink">Totality</a></h3>
|
|||
|
<p>By default, all keys must be present in a TypedDict. It is possible
|
|||
|
to override this by specifying <em>totality</em>. Here is how to do this
|
|||
|
using the class-based syntax:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Movie</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">,</span> <span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
<span class="n">year</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This means that a <code class="docutils literal notranslate"><span class="pre">Movie</span></code> TypedDict can have any of the keys omitted. Thus
|
|||
|
these are valid:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">m</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{}</span>
|
|||
|
<span class="n">m2</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'year'</span><span class="p">:</span> <span class="mi">2015</span><span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>A type checker is only expected to support a literal <code class="docutils literal notranslate"><span class="pre">False</span></code> or
|
|||
|
<code class="docutils literal notranslate"><span class="pre">True</span></code> as the value of the <code class="docutils literal notranslate"><span class="pre">total</span></code> argument. <code class="docutils literal notranslate"><span class="pre">True</span></code> is the
|
|||
|
default, and makes all items defined in the class body be required.</p>
|
|||
|
<p>The totality flag only applies to items defined in the body of the
|
|||
|
TypedDict definition. Inherited items won’t be affected, and instead
|
|||
|
use totality of the TypedDict type where they were defined. This makes
|
|||
|
it possible to have a combination of required and non-required keys in
|
|||
|
a single TypedDict type.</p>
|
|||
|
</section>
|
|||
|
<section id="alternative-syntax">
|
|||
|
<h3><a class="toc-backref" href="#alternative-syntax" role="doc-backlink">Alternative Syntax</a></h3>
|
|||
|
<p>This PEP also proposes an alternative syntax that can be backported to
|
|||
|
older Python versions such as 3.5 and 2.7 that don’t support the
|
|||
|
variable definition syntax introduced in <a class="pep reference internal" href="../pep-0526/" title="PEP 526 – Syntax for Variable Annotations">PEP 526</a>. It
|
|||
|
resembles the traditional syntax for defining named tuples:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Movie</span> <span class="o">=</span> <span class="n">TypedDict</span><span class="p">(</span><span class="s1">'Movie'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="s1">'year'</span><span class="p">:</span> <span class="nb">int</span><span class="p">})</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>It is also possible to specify totality using the alternative syntax:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Movie</span> <span class="o">=</span> <span class="n">TypedDict</span><span class="p">(</span><span class="s1">'Movie'</span><span class="p">,</span>
|
|||
|
<span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="s1">'year'</span><span class="p">:</span> <span class="nb">int</span><span class="p">},</span>
|
|||
|
<span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The semantics are equivalent to the class-based syntax. This syntax
|
|||
|
doesn’t support inheritance, however, and there is no way to
|
|||
|
have both required and non-required fields in a single type. The
|
|||
|
motivation for this is keeping the backwards compatible syntax as
|
|||
|
simple as possible while covering the most common use cases.</p>
|
|||
|
<p>A type checker is only expected to accept a dictionary display expression
|
|||
|
as the second argument to <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code>. In particular, a variable that
|
|||
|
refers to a dictionary object does not need to be supported, to simplify
|
|||
|
implementation.</p>
|
|||
|
</section>
|
|||
|
<section id="type-consistency">
|
|||
|
<h3><a class="toc-backref" href="#type-consistency" role="doc-backlink">Type Consistency</a></h3>
|
|||
|
<p>Informally speaking, <em>type consistency</em> is a generalization of the
|
|||
|
is-subtype-of relation to support the <code class="docutils literal notranslate"><span class="pre">Any</span></code> type. It is defined
|
|||
|
more formally in <a class="pep reference internal" href="../pep-0483/" title="PEP 483 – The Theory of Type Hints">PEP 483</a>. This section introduces the
|
|||
|
new, non-trivial rules needed to support type consistency for
|
|||
|
TypedDict types.</p>
|
|||
|
<p>First, any TypedDict type is consistent with <code class="docutils literal notranslate"><span class="pre">Mapping[str,</span> <span class="pre">object]</span></code>.
|
|||
|
Second, a TypedDict type <code class="docutils literal notranslate"><span class="pre">A</span></code> is consistent with TypedDict <code class="docutils literal notranslate"><span class="pre">B</span></code> if
|
|||
|
<code class="docutils literal notranslate"><span class="pre">A</span></code> is structurally compatible with <code class="docutils literal notranslate"><span class="pre">B</span></code>. This is true if and only
|
|||
|
if both of these conditions are satisfied:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>For each key in <code class="docutils literal notranslate"><span class="pre">B</span></code>, <code class="docutils literal notranslate"><span class="pre">A</span></code> has the corresponding key and the
|
|||
|
corresponding value type in <code class="docutils literal notranslate"><span class="pre">A</span></code> is consistent with the value type
|
|||
|
in <code class="docutils literal notranslate"><span class="pre">B</span></code>. For each key in <code class="docutils literal notranslate"><span class="pre">B</span></code>, the value type in <code class="docutils literal notranslate"><span class="pre">B</span></code> is also
|
|||
|
consistent with the corresponding value type in <code class="docutils literal notranslate"><span class="pre">A</span></code>.</li>
|
|||
|
<li>For each required key in <code class="docutils literal notranslate"><span class="pre">B</span></code>, the corresponding key is required
|
|||
|
in <code class="docutils literal notranslate"><span class="pre">A</span></code>. For each non-required key in <code class="docutils literal notranslate"><span class="pre">B</span></code>, the corresponding key
|
|||
|
is not required in <code class="docutils literal notranslate"><span class="pre">A</span></code>.</li>
|
|||
|
</ul>
|
|||
|
<p>Discussion:</p>
|
|||
|
<ul>
|
|||
|
<li>Value types behave invariantly, since TypedDict objects are mutable.
|
|||
|
This is similar to mutable container types such as <code class="docutils literal notranslate"><span class="pre">List</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Dict</span></code>. Example where this is relevant:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">a</span><span class="p">[</span><span class="s1">'x'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|||
|
|
|||
|
<span class="n">b</span><span class="p">:</span> <span class="n">B</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>
|
|||
|
<span class="n">f</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="c1"># Type check error: 'B' not compatible with 'A'</span>
|
|||
|
<span class="n">b</span><span class="p">[</span><span class="s1">'x'</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> <span class="c1"># Runtime error: None + 1</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>A TypedDict type with a required key is not consistent with a
|
|||
|
TypedDict type where the same key is a non-required key, since the
|
|||
|
latter allows keys to be deleted. Example where this is relevant:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">,</span> <span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="k">del</span> <span class="n">a</span><span class="p">[</span><span class="s1">'x'</span><span class="p">]</span>
|
|||
|
|
|||
|
<span class="n">b</span><span class="p">:</span> <span class="n">B</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>
|
|||
|
<span class="n">f</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="c1"># Type check error: 'B' not compatible with 'A'</span>
|
|||
|
<span class="n">b</span><span class="p">[</span><span class="s1">'x'</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> <span class="c1"># Runtime KeyError: 'x'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>A TypedDict type <code class="docutils literal notranslate"><span class="pre">A</span></code> with no key <code class="docutils literal notranslate"><span class="pre">'x'</span></code> is not consistent with a
|
|||
|
TypedDict type with a non-required key <code class="docutils literal notranslate"><span class="pre">'x'</span></code>, since at runtime
|
|||
|
the key <code class="docutils literal notranslate"><span class="pre">'x'</span></code> could be present and have an incompatible type
|
|||
|
(which may not be visible through <code class="docutils literal notranslate"><span class="pre">A</span></code> due to structural subtyping).
|
|||
|
Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">,</span> <span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
<span class="n">y</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">,</span> <span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">,</span> <span class="n">total</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
<span class="n">y</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">a</span><span class="p">[</span><span class="s1">'y'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">b</span><span class="p">:</span> <span class="n">B</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">f</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="c1"># Type check error: 'B' incompatible with 'A'</span>
|
|||
|
|
|||
|
<span class="n">c</span><span class="p">:</span> <span class="n">C</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'y'</span><span class="p">:</span> <span class="s1">'foo'</span><span class="p">}</span>
|
|||
|
<span class="n">g</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
|||
|
<span class="n">c</span><span class="p">[</span><span class="s1">'y'</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'bar'</span> <span class="c1"># Runtime error: int + str</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>A TypedDict isn’t consistent with any <code class="docutils literal notranslate"><span class="pre">Dict[...]</span></code> type, since
|
|||
|
dictionary types allow destructive operations, including
|
|||
|
<code class="docutils literal notranslate"><span class="pre">clear()</span></code>. They also allow arbitrary keys to be set, which
|
|||
|
would compromise type safety. Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">A</span><span class="p">):</span>
|
|||
|
<span class="n">y</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">d</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">d</span><span class="p">[</span><span class="s1">'y'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="c1"># Type check error: 'A' incompatible with Dict[str, int]</span>
|
|||
|
|
|||
|
<span class="n">b</span><span class="p">:</span> <span class="n">B</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'y'</span><span class="p">:</span> <span class="s1">'foo'</span><span class="p">}</span>
|
|||
|
<span class="n">g</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
|
|||
|
<span class="n">b</span><span class="p">[</span><span class="s1">'y'</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'bar'</span> <span class="c1"># Runtime error: int + str</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li>A TypedDict with all <code class="docutils literal notranslate"><span class="pre">int</span></code> values is not consistent with
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Mapping[str,</span> <span class="pre">int]</span></code>, since there may be additional non-<code class="docutils literal notranslate"><span class="pre">int</span></code>
|
|||
|
values not visible through the type, due to structural subtyping.
|
|||
|
These can be accessed using the <code class="docutils literal notranslate"><span class="pre">values()</span></code> and <code class="docutils literal notranslate"><span class="pre">items()</span></code>
|
|||
|
methods in <code class="docutils literal notranslate"><span class="pre">Mapping</span></code>, for example. Example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">TypedDict</span><span class="p">):</span>
|
|||
|
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
|
|||
|
<span class="n">y</span><span class="p">:</span> <span class="nb">str</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">sum_values</span><span class="p">(</span><span class="n">m</span><span class="p">:</span> <span class="n">Mapping</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">])</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
|||
|
<span class="n">n</span> <span class="o">=</span> <span class="mi">0</span>
|
|||
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
|
|||
|
<span class="n">n</span> <span class="o">+=</span> <span class="n">v</span> <span class="c1"># Runtime error</span>
|
|||
|
<span class="k">return</span> <span class="n">n</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">A</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="n">sum_values</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="c1"># Error: 'A' incompatible with Mapping[str, int]</span>
|
|||
|
|
|||
|
<span class="n">b</span><span class="p">:</span> <span class="n">B</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'y'</span><span class="p">:</span> <span class="s1">'foo'</span><span class="p">}</span>
|
|||
|
<span class="n">f</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</section>
|
|||
|
<section id="supported-and-unsupported-operations">
|
|||
|
<h3><a class="toc-backref" href="#supported-and-unsupported-operations" role="doc-backlink">Supported and Unsupported Operations</a></h3>
|
|||
|
<p>Type checkers should support restricted forms of most <code class="docutils literal notranslate"><span class="pre">dict</span></code>
|
|||
|
operations on TypedDict objects. The guiding principle is that
|
|||
|
operations not involving <code class="docutils literal notranslate"><span class="pre">Any</span></code> types should be rejected by type
|
|||
|
checkers if they may violate runtime type safety. Here are some of
|
|||
|
the most important type safety violations to prevent:</p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>A required key is missing.</li>
|
|||
|
<li>A value has an invalid type.</li>
|
|||
|
<li>A key that is not defined in the TypedDict type is added.</li>
|
|||
|
</ol>
|
|||
|
<p>A key that is not a literal should generally be rejected, since its
|
|||
|
value is unknown during type checking, and thus can cause some of the
|
|||
|
above violations. (<a class="reference internal" href="#use-of-final-values-and-literal-types">Use of Final Values and Literal Types</a>
|
|||
|
generalizes this to cover final names and literal types.)</p>
|
|||
|
<p>The use of a key that is not known to exist should be reported as an
|
|||
|
error, even if this wouldn’t necessarily generate a runtime type
|
|||
|
error. These are often mistakes, and these may insert values with an
|
|||
|
invalid type if structural subtyping hides the types of certain items.
|
|||
|
For example, <code class="docutils literal notranslate"><span class="pre">d['x']</span> <span class="pre">=</span> <span class="pre">1</span></code> should generate a type check error if
|
|||
|
<code class="docutils literal notranslate"><span class="pre">'x'</span></code> is not a valid key for <code class="docutils literal notranslate"><span class="pre">d</span></code> (which is assumed to be a
|
|||
|
TypedDict type).</p>
|
|||
|
<p>Extra keys included in TypedDict object construction should also be
|
|||
|
caught. In this example, the <code class="docutils literal notranslate"><span class="pre">director</span></code> key is not defined in
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Movie</span></code> and is expected to generate an error from a type checker:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">m</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
|
|||
|
<span class="n">name</span><span class="o">=</span><span class="s1">'Alien'</span><span class="p">,</span>
|
|||
|
<span class="n">year</span><span class="o">=</span><span class="mi">1979</span><span class="p">,</span>
|
|||
|
<span class="n">director</span><span class="o">=</span><span class="s1">'Ridley Scott'</span><span class="p">)</span> <span class="c1"># error: Unexpected key 'director'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Type checkers should reject the following operations on TypedDict
|
|||
|
objects as unsafe, even though they are valid for normal dictionaries:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>Operations with arbitrary <code class="docutils literal notranslate"><span class="pre">str</span></code> keys (instead of string literals
|
|||
|
or other expressions with known string values) should generally be
|
|||
|
rejected. This involves both destructive operations such as setting
|
|||
|
an item and read-only operations such as subscription expressions.
|
|||
|
As an exception to the above rule, <code class="docutils literal notranslate"><span class="pre">d.get(e)</span></code> and <code class="docutils literal notranslate"><span class="pre">e</span> <span class="pre">in</span> <span class="pre">d</span></code>
|
|||
|
should be allowed for TypedDict objects, for an arbitrary expression
|
|||
|
<code class="docutils literal notranslate"><span class="pre">e</span></code> with type <code class="docutils literal notranslate"><span class="pre">str</span></code>. The motivation is that these are safe and
|
|||
|
can be useful for introspecting TypedDict objects. The static type
|
|||
|
of <code class="docutils literal notranslate"><span class="pre">d.get(e)</span></code> should be <code class="docutils literal notranslate"><span class="pre">object</span></code> if the string value of <code class="docutils literal notranslate"><span class="pre">e</span></code>
|
|||
|
cannot be determined statically.</li>
|
|||
|
<li><code class="docutils literal notranslate"><span class="pre">clear()</span></code> is not safe since it could remove required keys, some of
|
|||
|
which may not be directly visible because of structural
|
|||
|
subtyping. <code class="docutils literal notranslate"><span class="pre">popitem()</span></code> is similarly unsafe, even if all known
|
|||
|
keys are not required (<code class="docutils literal notranslate"><span class="pre">total=False</span></code>).</li>
|
|||
|
<li><code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">obj['key']</span></code> should be rejected unless <code class="docutils literal notranslate"><span class="pre">'key'</span></code> is a
|
|||
|
non-required key.</li>
|
|||
|
</ul>
|
|||
|
<p>Type checkers may allow reading an item using <code class="docutils literal notranslate"><span class="pre">d['x']</span></code> even if
|
|||
|
the key <code class="docutils literal notranslate"><span class="pre">'x'</span></code> is not required, instead of requiring the use of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">d.get('x')</span></code> or an explicit <code class="docutils literal notranslate"><span class="pre">'x'</span> <span class="pre">in</span> <span class="pre">d</span></code> check. The rationale is
|
|||
|
that tracking the existence of keys is difficult to implement in full
|
|||
|
generality, and that disallowing this could require many changes to
|
|||
|
existing code.</p>
|
|||
|
<p>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.</p>
|
|||
|
</section>
|
|||
|
<section id="use-of-final-values-and-literal-types">
|
|||
|
<h3><a class="toc-backref" href="#use-of-final-values-and-literal-types" role="doc-backlink">Use of Final Values and Literal Types</a></h3>
|
|||
|
<p>Type checkers should allow final names (<a class="pep reference internal" href="../pep-0591/" title="PEP 591 – Adding a final qualifier to typing">PEP 591</a>) with
|
|||
|
string values to be used instead of string literals in operations on
|
|||
|
TypedDict objects. For example, this is valid:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">YEAR</span><span class="p">:</span> <span class="n">Final</span> <span class="o">=</span> <span class="s1">'year'</span>
|
|||
|
|
|||
|
<span class="n">m</span><span class="p">:</span> <span class="n">Movie</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Alien'</span><span class="p">,</span> <span class="s1">'year'</span><span class="p">:</span> <span class="mi">1979</span><span class="p">}</span>
|
|||
|
<span class="n">years_since_epoch</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">YEAR</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1970</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Similarly, an expression with a suitable literal type
|
|||
|
(<a class="pep reference internal" href="../pep-0586/" title="PEP 586 – Literal Types">PEP 586</a>) can be used instead of a literal value:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_value</span><span class="p">(</span><span class="n">movie</span><span class="p">:</span> <span class="n">Movie</span><span class="p">,</span>
|
|||
|
<span class="n">key</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">'year'</span><span class="p">,</span> <span class="s1">'name'</span><span class="p">])</span> <span class="o">-></span> <span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
|
|||
|
<span class="k">return</span> <span class="n">movie</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Type checkers are only expected to support actual string literals, not
|
|||
|
final names or literal types, for specifying keys in a TypedDict type
|
|||
|
definition. Also, only a boolean literal can be used to specify
|
|||
|
totality in a TypedDict definition. The motivation for this is to
|
|||
|
make type declarations self-contained, and to simplify the
|
|||
|
implementation of type checkers.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="backwards-compatibility">
|
|||
|
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
|
|||
|
<p>To retain backwards compatibility, type checkers should not infer a
|
|||
|
TypedDict type unless it is sufficiently clear that this is desired by
|
|||
|
the programmer. When unsure, an ordinary dictionary type should be
|
|||
|
inferred. Otherwise existing code that type checks without errors may
|
|||
|
start generating errors once TypedDict support is added to the type
|
|||
|
checker, since TypedDict types are more restrictive than dictionary
|
|||
|
types. In particular, they aren’t subtypes of dictionary types.</p>
|
|||
|
</section>
|
|||
|
<section id="reference-implementation">
|
|||
|
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
|||
|
<p>The mypy <a class="footnote-reference brackets" href="#mypy" id="id2">[2]</a> type checker supports TypedDict types. A reference
|
|||
|
implementation of the runtime component is provided in the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">typing_extensions</span></code> <a class="footnote-reference brackets" href="#typing-extensions" id="id3">[3]</a> module. The original
|
|||
|
implementation was in the <code class="docutils literal notranslate"><span class="pre">mypy_extensions</span></code> <a class="footnote-reference brackets" href="#mypy-extensions" id="id4">[4]</a>
|
|||
|
module.</p>
|
|||
|
</section>
|
|||
|
<section id="rejected-alternatives">
|
|||
|
<h2><a class="toc-backref" href="#rejected-alternatives" role="doc-backlink">Rejected Alternatives</a></h2>
|
|||
|
<p>Several proposed ideas were rejected. The current set of features
|
|||
|
seem to cover a lot of ground, and it was not clear which of the
|
|||
|
proposed extensions would be more than marginally useful. This PEP
|
|||
|
defines a baseline feature that can be potentially extended later.</p>
|
|||
|
<p>These are rejected on principle, as incompatible with the spirit of
|
|||
|
this proposal:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>TypedDict isn’t extensible, and it addresses only a specific use
|
|||
|
case. TypedDict objects are regular dictionaries at runtime, and
|
|||
|
TypedDict cannot be used with other dictionary-like or mapping-like
|
|||
|
classes, including subclasses of <code class="docutils literal notranslate"><span class="pre">dict</span></code>. There is no way to add
|
|||
|
methods to TypedDict types. The motivation here is simplicity.</li>
|
|||
|
<li>TypedDict type definitions could plausibly used to perform runtime
|
|||
|
type checking of dictionaries. For example, they could be used to
|
|||
|
validate that a JSON object conforms to the schema specified by a
|
|||
|
TypedDict type. This PEP doesn’t include such functionality, since
|
|||
|
the focus of this proposal is static type checking only, and other
|
|||
|
existing types do not support this, as discussed in <a class="reference internal" href="#class-based-syntax">Class-based
|
|||
|
syntax</a>. Such functionality can be provided by a third-party
|
|||
|
library using the <code class="docutils literal notranslate"><span class="pre">typing_inspect</span></code> <a class="footnote-reference brackets" href="#typing-inspect" id="id5">[5]</a> third-party
|
|||
|
module, for example.</li>
|
|||
|
<li>TypedDict types can’t be used in <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> or <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>
|
|||
|
checks. The reasoning is similar to why runtime type checks aren’t
|
|||
|
supported in general with many type hints.</li>
|
|||
|
</ul>
|
|||
|
<p>These features were left out from this PEP, but they are potential
|
|||
|
extensions to be added in the future:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li>TypedDict doesn’t support providing a <em>default value type</em> for keys
|
|||
|
that are not explicitly defined. This would allow arbitrary keys to
|
|||
|
be used with a TypedDict object, and only explicitly enumerated keys
|
|||
|
would receive special treatment compared to a normal, uniform
|
|||
|
dictionary type.</li>
|
|||
|
<li>There is no way to individually specify whether each key is required
|
|||
|
or not. No proposed syntax was clear enough, and we expect that
|
|||
|
there is limited need for this.</li>
|
|||
|
<li>TypedDict can’t be used for specifying the type of a <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>
|
|||
|
argument. This would allow restricting the allowed keyword
|
|||
|
arguments and their types. According to <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">PEP 484</a>, using a TypedDict
|
|||
|
type as the type of <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> means that the TypedDict is valid
|
|||
|
as the <em>value</em> of arbitrary keyword arguments, but it doesn’t
|
|||
|
restrict which keyword arguments should be allowed. The syntax
|
|||
|
<code class="docutils literal notranslate"><span class="pre">**kwargs:</span> <span class="pre">Expand[T]</span></code> has been proposed for this <a class="footnote-reference brackets" href="#expand" id="id6">[6]</a>.</li>
|
|||
|
</ul>
|
|||
|
</section>
|
|||
|
<section id="acknowledgements">
|
|||
|
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
|||
|
<p>David Foster contributed the initial implementation of TypedDict types
|
|||
|
to mypy. Improvements to the implementation have been contributed by
|
|||
|
at least the author (Jukka Lehtosalo), Ivan Levkivskyi, Gareth T,
|
|||
|
Michael Lee, Dominik Miedzinski, Roy Williams and Max Moroz.</p>
|
|||
|
</section>
|
|||
|
<section id="references">
|
|||
|
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
|||
|
<aside class="footnote-list brackets">
|
|||
|
<aside class="footnote brackets" id="dataclasses-json" role="doc-footnote">
|
|||
|
<dt class="label" id="dataclasses-json">[<a href="#id1">1</a>]</dt>
|
|||
|
<dd>Dataclasses JSON
|
|||
|
(<a class="reference external" href="https://github.com/lidatong/dataclasses-json">https://github.com/lidatong/dataclasses-json</a>)</aside>
|
|||
|
<aside class="footnote brackets" id="mypy" role="doc-footnote">
|
|||
|
<dt class="label" id="mypy">[<a href="#id2">2</a>]</dt>
|
|||
|
<dd><a class="reference external" href="http://www.mypy-lang.org/">http://www.mypy-lang.org/</a></aside>
|
|||
|
<aside class="footnote brackets" id="typing-extensions" role="doc-footnote">
|
|||
|
<dt class="label" id="typing-extensions">[<a href="#id3">3</a>]</dt>
|
|||
|
<dd><a class="reference external" href="https://github.com/python/typing/tree/master/typing_extensions">https://github.com/python/typing/tree/master/typing_extensions</a></aside>
|
|||
|
<aside class="footnote brackets" id="mypy-extensions" role="doc-footnote">
|
|||
|
<dt class="label" id="mypy-extensions">[<a href="#id4">4</a>]</dt>
|
|||
|
<dd><a class="reference external" href="https://github.com/python/mypy_extensions">https://github.com/python/mypy_extensions</a></aside>
|
|||
|
<aside class="footnote brackets" id="typing-inspect" role="doc-footnote">
|
|||
|
<dt class="label" id="typing-inspect">[<a href="#id5">5</a>]</dt>
|
|||
|
<dd><a class="reference external" href="https://github.com/ilevkivskyi/typing_inspect">https://github.com/ilevkivskyi/typing_inspect</a></aside>
|
|||
|
<aside class="footnote brackets" id="expand" role="doc-footnote">
|
|||
|
<dt class="label" id="expand">[<a href="#id6">6</a>]</dt>
|
|||
|
<dd><a class="reference external" href="https://github.com/python/mypy/issues/4441">https://github.com/python/mypy/issues/4441</a></aside>
|
|||
|
</aside>
|
|||
|
</section>
|
|||
|
<section id="copyright">
|
|||
|
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
|||
|
<p>This document has been placed in the public domain.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<hr class="docutils" />
|
|||
|
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0589.rst">https://github.com/python/peps/blob/main/peps/pep-0589.rst</a></p>
|
|||
|
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0589.rst">2024-06-11 22:12:09 GMT</a></p>
|
|||
|
|
|||
|
</article>
|
|||
|
<nav id="pep-sidebar">
|
|||
|
<h2>Contents</h2>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
|||
|
<li><a class="reference internal" href="#class-based-syntax">Class-based Syntax</a></li>
|
|||
|
<li><a class="reference internal" href="#using-typeddict-types">Using TypedDict Types</a></li>
|
|||
|
<li><a class="reference internal" href="#inheritance">Inheritance</a></li>
|
|||
|
<li><a class="reference internal" href="#totality">Totality</a></li>
|
|||
|
<li><a class="reference internal" href="#alternative-syntax">Alternative Syntax</a></li>
|
|||
|
<li><a class="reference internal" href="#type-consistency">Type Consistency</a></li>
|
|||
|
<li><a class="reference internal" href="#supported-and-unsupported-operations">Supported and Unsupported Operations</a></li>
|
|||
|
<li><a class="reference internal" href="#use-of-final-values-and-literal-types">Use of Final Values and Literal Types</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
|
|||
|
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a></li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<br>
|
|||
|
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0589.rst">Page Source (GitHub)</a>
|
|||
|
</nav>
|
|||
|
</section>
|
|||
|
<script src="../_static/colour_scheme.js"></script>
|
|||
|
<script src="../_static/wrap_tables.js"></script>
|
|||
|
<script src="../_static/sticky_banner.js"></script>
|
|||
|
</body>
|
|||
|
</html>
|