Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 781 – Make TYPE_CHECKING a built-in constant

Author:
Inada Naoki <songofacandy at gmail.com>
Discussions-To:
Discourse thread
Status:
Draft
Type:
Standards Track
Topic:
Typing
Created:
24-Mar-2025
Python-Version:
3.14
Post-History:
11-Jan-2025, 24-Mar-2025

Table of Contents

Abstract

This PEP proposes adding a new built-in variable, TYPE_CHECKING, to improve the experience of writing Python code with type annotations. It is evaluated as True when the code is being analyzed by a static type checker, and as False during normal runtime execution. Unlike typing.TYPE_CHECKING, which this variable replaces, it does not require an import statement.

Motivation

Type annotations were defined for Python by PEP 484, and have enjoyed widespread adoption. A challenge with fully-annotated code is that many more imports are required in order to bring the relevant name into scope, potentially causing import cycles without careful design. This has been recognized by PEP 563 and later PEP 649, which introduce two different mechanisms for deferred evaluation of type annotations. As PEP 563 notes, “type hints are … not computationally free”. The typing.TYPE_CHECKING constant was thus introduced, initially to aid in breaking cyclic imports.

In situations where startup time is critical, such as command-line interfaces, applications, or core libraries, programmers may place all import statements not required for runtime execution within a ‘TYPE_CHECKING block’, or even defer certain imports to within functions. The typing module itself though can take as much as 10ms to import, longer than Python takes to initialize. The time taken to import the typing module clearly cannot be ignored.

To avoid importing TYPE_CHECKING from typing, developers currently define a module-level variable such as TYPE_CHECKING = False or use code like if False:  # TYPE_CHECKING. Providing a standard method will allow many tools to implement the same behavior consistently. It will also allow third-party tools in the ecosystem to standardize on a single behavior with guaranteed semantics, as for example some static type checkers currently do not permit local constants, only recognizing typing.TYPE_CHECKING.

Specification

TYPE_CHECKING is a built-in constant and its value is False. Unlike True, False, None, and __debug__, TYPE_CHECKING is not a real constant; assigning to it will not raise a SyntaxError.

Static type checkers must treat TYPE_CHECKING as True, similar to typing.TYPE_CHECKING.

If this PEP is accepted, the new TYPE_CHECKING constant will be the preferred approach and importing typing.TYPE_CHECKING will be deprecated. To minimize the runtime impact of typing, this deprecation will generate DeprecationWarning no sooner than Python 3.13’s end of life, scheduled for October 2029.

Instead, type checkers may warn about such deprecated usage when the target version of the checked program is signalled to be Python 3.14 or newer.

Backwards Compatibility

Since TYPE_CHECKING doesn’t prohibit assignment, existing code using TYPE_CHECKING will continue to work.

# This code will continue to work
TYPE_CHECKING = False
from typing import TYPE_CHECKING

User can remove the assignment to TYPE_CHECKING after they stop using Python 3.13 or older versions.

How to Teach This

  • Use if TYPE_CHECKING: for skipping type-checking code at runtime.
  • Use from typing import TYPE_CHECKING to support Python versions before 3.14.
  • Workarounds like TYPE_CHECKING = False or if False:  # TYPE_CHECKING will continue to work, but are not recommended.

Reference Implementation

Rejected Ideas

Eliminate type-checking-only code

It is considered to add real constant named __type_checking__ to eliminate type-checking-only code at compile time.

However, adding real constant to language increase complexity of the language. Benefit from eliminating type-checking-only code is estimated to be not enough to justify the complexity.

Optimize import typing

Future optimizations may eliminate the need to avoid importing the typing module for startup time.

Even with such optimizations, there will still be use cases where minimizing imports is beneficial, such as running Python on embedded systems or in browsers.

Therefore, defining a constant for skipping type-checking-only code outside the typing module remains valuable.


Source: https://github.com/python/peps/blob/main/peps/pep-0781.rst

Last modified: 2025-04-02 13:03:17 GMT