CINXE.COM
PEP 613 – Explicit Type Aliases | peps.python.org
<!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 613 – Explicit Type Aliases | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0613/"> <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 613 – Explicit Type Aliases | peps.python.org'> <meta property="og:description" content="Type aliases are user-specified types which may be as complex as any type hint, and are specified with a simple variable assignment on a module top level."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0613/"> <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="Type aliases are user-specified types which may be as complex as any type hint, and are specified with a simple variable assignment on a module top level."> <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 613</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 613 – Explicit Type Aliases</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Shannon Zhu <szhu at fb.com></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">Discussions-To<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/thread/MWRJOBEEEMFVXE7CAKO7B4P46IPM4AN3/">Typing-SIG thread</a></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><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-even">Topic<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="../topic/typing/">Typing</a></dd> <dt class="field-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">21-Jan-2020</dd> <dt class="field-even">Python-Version<span class="colon">:</span></dt> <dd class="field-even">3.10</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd">21-Jan-2020</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><ul> <li><a class="reference internal" href="#forward-references">Forward References:</a></li> <li><a class="reference internal" href="#error-messaging">Error Messaging:</a></li> <li><a class="reference internal" href="#scope-restrictions">Scope Restrictions:</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a></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-ideas">Rejected Ideas</a></li> <li><a class="reference internal" href="#version-history">Version History</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 important"> <p class="admonition-title">Important</p> <p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/aliases.html#type-aliases" title="(in typing)"><span>Type aliases</span></a> and <a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.TypeAlias" title="(in Python v3.13)"><code class="xref py py-data docutils literal notranslate"><span class="pre">typing.TypeAlias</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>Type aliases are user-specified types which may be as complex as any type hint, and are specified with a simple variable assignment on a module top level.</p> <p>This PEP formalizes a way to explicitly declare an assignment as a type alias.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>Type aliases are declared as top level variable assignments. In <a class="pep reference internal" href="../pep-0484/#type-aliases" title="PEP 484 – Type Hints § Type aliases">PEP 484</a>, the distinction between a valid type alias and a global variable was implicitly determined: if a top level assignment is unannotated, and the assigned value is a valid type, then the name being assigned to is a valid type alias. Otherwise, that name is simply a global value that cannot be used as a type hint.</p> <p>These implicit type alias declaration rules create confusion when type aliases involve forward references, invalid types, or violate other restrictions enforced on type alias declaration. Because the distinction between an unannotated value and a type alias is implicit, ambiguous or incorrect type alias declarations implicitly default to a valid value assignment. This creates expressions that are impossible to express as type aliases and punts error diagnosis of malformed type aliases downstream.</p> <p>The following examples each include an illustration of some of the suboptimal or confusing behaviors resulting from existing implicit alias declarations. We also introduce explicit aliases of the format <code class="docutils literal notranslate"><span class="pre">TypeName:</span> <span class="pre">TypeAlias</span> <span class="pre">=</span> <span class="pre">Expression</span></code> here for the sake of comparison, but the syntax is discussed in further detail in later sections.</p> <section id="forward-references"> <h3><a class="toc-backref" href="#forward-references" role="doc-backlink">Forward References:</a></h3> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType</span> <span class="o">=</span> <span class="s2">"ClassName"</span> <span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="n">MyType</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>This code snippet should not error so long as <code class="docutils literal notranslate"><span class="pre">ClassName</span></code> is defined later on. However, a type checker is forced to assume that MyType is a value assignment rather than a type alias, and therefore may throw spurious errors that (1) <code class="docutils literal notranslate"><span class="pre">MyType</span></code> is an unannotated global string, and (2) <code class="docutils literal notranslate"><span class="pre">MyType</span></code> cannot be used as a return annotation because it is not a valid type.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="s2">"ClassName"</span> <span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="n">MyType</span><span class="p">:</span> <span class="o">...</span> </pre></div> </div> <p>Explicit aliases remove ambiguity so neither of the above errors will be thrown. Additionally, if something is wrong with <code class="docutils literal notranslate"><span class="pre">ClassName</span></code> (i.e., it’s not actually defined later), the type checker can throw an error.</p> </section> <section id="error-messaging"> <h3><a class="toc-backref" href="#error-messaging" role="doc-backlink">Error Messaging:</a></h3> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType1</span> <span class="o">=</span> <span class="n">InvalidType</span> <span class="n">MyType2</span> <span class="o">=</span> <span class="n">MyGeneric</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span> <span class="c1"># i.e., intention was MyGeneric[int]</span> </pre></div> </div> <p>A type checker should warn on this code snippet that <code class="docutils literal notranslate"><span class="pre">InvalidType</span></code> is not a valid type, and therefore cannot be used to annotate an expression or to construct a type alias. Instead, type checkers are forced to throw spurious errors that (1) <code class="docutils literal notranslate"><span class="pre">MyType</span></code> is a global expression missing an annotation, and (2) <code class="docutils literal notranslate"><span class="pre">MyType</span></code> is not a valid type in all usages of <code class="docutils literal notranslate"><span class="pre">MyType</span></code> across the codebase.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType1</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">InvalidType</span> <span class="n">MyType2</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">MyGeneric</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span> </pre></div> </div> <p>With explicit aliases, the type checker has enough information to error on the actual definition of the bad type alias, and explain why: that <code class="docutils literal notranslate"><span class="pre">MyGeneric(int)</span></code> and <code class="docutils literal notranslate"><span class="pre">InvalidType</span></code> are not valid types. When the value expression is no longer evaluated as a global value, unactionable type errors on all usages of <code class="docutils literal notranslate"><span class="pre">MyType</span></code> across the codebase can be suppressed.</p> </section> <section id="scope-restrictions"> <h3><a class="toc-backref" href="#scope-restrictions" role="doc-backlink">Scope Restrictions:</a></h3> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="p">:</span> <span class="n">x</span> <span class="o">=</span> <span class="n">ClassName</span> <span class="n">y</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">ClassName</span> <span class="n">z</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">ClassName</span><span class="p">]</span> <span class="o">=</span> <span class="n">ClassName</span> </pre></div> </div> <p>Type aliases are valid within class scope, both implicitly (<code class="docutils literal notranslate"><span class="pre">x</span></code>) and explicitly (<code class="docutils literal notranslate"><span class="pre">y</span></code>). If the line should be interpreted as a class variable, it must be explicitly annotated (<code class="docutils literal notranslate"><span class="pre">z</span></code>).</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">ClassName</span> <span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="n">x</span> <span class="o">=</span> <span class="n">ClassName</span> </pre></div> </div> <p>The outer <code class="docutils literal notranslate"><span class="pre">x</span></code> is a valid type alias, but type checkers must error if the inner <code class="docutils literal notranslate"><span class="pre">x</span></code> is ever used as a type because type aliases cannot be defined inside of a function. This is confusing because the alias declaration rule is not explicit, and because a type error will not be thrown on the location of the inner type alias declaration but rather on every one of its subsequent use cases.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">ClassName</span> <span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="n">x</span> <span class="o">=</span> <span class="n">ClassName</span> <span class="k">def</span><span class="w"> </span><span class="nf">bar</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="n">x</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">ClassName</span> </pre></div> </div> <p>With explicit aliases, the outer assignment is still a valid type variable. Inside <code class="docutils literal notranslate"><span class="pre">foo</span></code>, the inner assignment should be interpreted as <code class="docutils literal notranslate"><span class="pre">x:</span> <span class="pre">Type[ClassName]</span></code>. Inside <code class="docutils literal notranslate"><span class="pre">bar</span></code>, the type checker should raise a clear error, communicating to the author that type aliases cannot be defined inside a function.</p> </section> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>The explicit alias declaration syntax clearly differentiates between the three possible kinds of assignments: typed global expressions, untyped global expressions, and type aliases. This avoids the existence of assignments that break type checking when an annotation is added, and avoids classifying the nature of the assignment based on the type of the value.</p> <p>Implicit syntax (pre-existing):</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># untyped global expression</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># typed global expression</span> <span class="n">x</span> <span class="o">=</span> <span class="nb">int</span> <span class="c1"># type alias</span> <span class="n">x</span><span class="p">:</span> <span class="n">Type</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="c1"># typed global expression</span> </pre></div> </div> <p>Explicit syntax:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># untyped global expression</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># typed global expression</span> <span class="n">x</span> <span class="o">=</span> <span class="nb">int</span> <span class="c1"># untyped global expression (see note below)</span> <span class="n">x</span><span class="p">:</span> <span class="n">Type</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="c1"># typed global expression</span> <span class="n">x</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="nb">int</span> <span class="c1"># type alias</span> <span class="n">x</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="s2">"MyClass"</span> <span class="c1"># type alias</span> </pre></div> </div> <p>Note: The examples above illustrate implicit and explicit alias declarations in isolation. For the sake of backwards compatibility, type checkers should support both simultaneously, meaning an untyped global expression <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">int</span></code> will still be considered a valid type alias.</p> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>Explicit aliases provide an alternative way to declare type aliases, but all pre-existing code and old alias declarations will work as before.</p> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>The <a class="reference external" href="https://pyre-check.org/">Pyre</a> type checker supports explicit type alias declarations.</p> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <p>Some alternative syntaxes were considered for explicit aliases:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType</span><span class="p">:</span> <span class="n">TypeAlias</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> </pre></div> </div> <p>This looks a lot like an uninitialized variable.</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyType</span> <span class="o">=</span> <span class="n">TypeAlias</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> </pre></div> </div> <p>Along with the option above, this format potentially adds confusion around what the runtime value of <code class="docutils literal notranslate"><span class="pre">MyType</span></code> is.</p> <p>In comparison, the chosen syntax option <code class="docutils literal notranslate"><span class="pre">MyType:</span> <span class="pre">TypeAlias</span> <span class="pre">=</span> <span class="pre">int</span></code> is appealing because it still sticks with the <code class="docutils literal notranslate"><span class="pre">MyType</span> <span class="pre">=</span> <span class="pre">int</span></code> assignment syntax, and adds some information for the type checker purely as an annotation.</p> </section> <section id="version-history"> <h2><a class="toc-backref" href="#version-history" role="doc-backlink">Version History</a></h2> <ul class="simple"> <li>2021-11-16<ul> <li>Allow <code class="docutils literal notranslate"><span class="pre">TypeAlias</span></code> inside class scope</li> </ul> </li> </ul> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0613.rst">https://github.com/python/peps/blob/main/peps/pep-0613.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0613.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><ul> <li><a class="reference internal" href="#forward-references">Forward References:</a></li> <li><a class="reference internal" href="#error-messaging">Error Messaging:</a></li> <li><a class="reference internal" href="#scope-restrictions">Scope Restrictions:</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a></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-ideas">Rejected Ideas</a></li> <li><a class="reference internal" href="#version-history">Version History</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-0613.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>