Skip to content

Commit 87cf871

Browse files
methaneAA-Turnerhugovk
authored
PEP 781: Make TYPE_CHECKING a built-in constant (#4318)
Co-authored-by: Adam Turner <[email protected]> Co-authored-by: Hugo van Kemenade <[email protected]>
1 parent baaaa7f commit 87cf871

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ peps/pep-0777.rst @warsaw
660660
peps/pep-0779.rst @Yhg1s @colesbury @mpage
661661
peps/pep-0780.rst @lysnikolaou
662662
# ...
663+
peps/pep-0781.rst @methane
664+
# ...
663665
peps/pep-0789.rst @njsmith
664666
# ...
665667
peps/pep-0801.rst @warsaw

peps/pep-0781.rst

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
PEP: 781
2+
Title: Make ``TYPE_CHECKING`` a built-in constant
3+
Author: Inada Naoki <[email protected]>
4+
Discussions-To: https://discuss.python.org/t/85728
5+
Status: Draft
6+
Type: Standards Track
7+
Topic: Typing
8+
Created: 24-Mar-2025
9+
Python-Version: 3.14
10+
Post-History: `11-Jan-2025 <https://discuss.python.org/t/76766>`__,
11+
`24-Mar-2025 <https://discuss.python.org/t/85728>`__,
12+
13+
14+
Abstract
15+
========
16+
17+
This PEP proposes adding a new built-in variable, :data:`!TYPE_CHECKING`, to
18+
improve the experience of writing Python code with type annotations. It is
19+
evaluated as ``True`` when the code is being analyzed by a static type checker,
20+
and as ``False`` during normal runtime execution. Unlike
21+
:data:`typing.TYPE_CHECKING`, which this variable replaces, it does not require
22+
an import statement.
23+
24+
25+
Motivation
26+
==========
27+
28+
Type annotations were defined for Python by :pep:`484`, and have enjoyed
29+
widespread adoption. A challenge with fully-annotated code is that many
30+
more imports are required in order to bring the relevant name into scope,
31+
potentially causing import cycles without careful design. This has been
32+
recognized by :pep:`563` and later :pep:`649`, which introduce two different
33+
mechanisms for deferred evaluation of type annotations. As PEP 563 notes,
34+
"type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING`
35+
constant was thus introduced__, initially to aid in breaking cyclic imports.
36+
37+
__ https://github.com/python/typing/issues/230
38+
39+
In situations where startup time is critical, such as command-line interfaces,
40+
applications, or core libraries, programmers may place all import statements
41+
not required for runtime execution within a 'TYPE_CHECKING block', or even
42+
defer certain imports to within functions. The ``typing`` module itself though
43+
can take as much as 10ms to import, longer than Python takes to initialize.
44+
The time taken to import the ``typing`` module clearly cannot be ignored.
45+
46+
To avoid importing ``TYPE_CHECKING`` from ``typing``, developers currently
47+
define a module-level variable such as ``TYPE_CHECKING = False`` or use code
48+
like ``if False: # TYPE_CHECKING``. Providing a standard method will allow
49+
many tools to implement the same behavior consistently. It will also allow
50+
third-party tools in the ecosystem to standardize on a single behavior
51+
with guaranteed semantics, as for example some static type checkers currently
52+
do not permit local constants, only recognizing ``typing.TYPE_CHECKING``.
53+
54+
55+
Specification
56+
=============
57+
58+
``TYPE_CHECKING`` is a built-in constant and its value is ``False``.
59+
Unlike ``True``, ``False``, ``None``, and ``__debug__``, ``TYPE_CHECKING`` is
60+
not a real constant; assigning to it will not raise a ``SyntaxError``.
61+
62+
Static type checkers must treat ``TYPE_CHECKING`` as ``True``, similar to
63+
:data:`typing.TYPE_CHECKING`.
64+
65+
If this PEP is accepted, the new ``TYPE_CHECKING`` constant will be
66+
the preferred approach, instead of the existing ``typing.TYPE_CHECKING``.
67+
However, ``typing.TYPE_CHECKING`` will not be deprecated in the foreseeable
68+
future.
69+
70+
71+
Backwards Compatibility
72+
=======================
73+
74+
Since ``TYPE_CHECKING`` doesn't prohibit assignment, existing code using
75+
``TYPE_CHECKING`` will continue to work.
76+
77+
.. code-block:: python
78+
79+
# This code will continue to work
80+
TYPE_CHECKING = False
81+
from typing import TYPE_CHECKING
82+
83+
84+
User can remove the assignment to ``TYPE_CHECKING`` after they stop using
85+
Python 3.13 or older versions.
86+
87+
88+
How to Teach This
89+
=================
90+
91+
* Use ``if TYPE_CHECKING:`` for skipping type-checking code at runtime.
92+
* Use ``from typing import TYPE_CHECKING`` to support Python versions before
93+
3.14.
94+
* Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING``
95+
will continue to work, but are not recommended.
96+
97+
98+
Reference Implementation
99+
========================
100+
101+
* `python/cpython#131793 <https://github.com/python/cpython/pull/131793>`__
102+
103+
104+
Rejected Ideas
105+
==============
106+
107+
Eliminate type-checking-only code
108+
---------------------------------
109+
110+
It is considered to add real constant named ``__type_checking__``
111+
to eliminate type-checking-only code at compile time.
112+
113+
However, adding real constant to language increase complexity of the language.
114+
Benefit from eliminating type-checking-only code is estimated to be not enough
115+
to justify the complexity.
116+
117+
118+
Copyright
119+
=========
120+
121+
This document is placed in the public domain or under the
122+
CC0-1.0-Universal license, whichever is more permissive.

0 commit comments

Comments
 (0)