Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PEP 647: Incorporated feedback from Guido about terminology and type relationship between bool and TypeGuard #1765

Merged
merged 15 commits into from
Jan 16, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions pep-0647.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,18 @@ TypeGuard Type
--------------

This PEP introduces the symbol ``TypeGuard`` exported from the ``typing``
module. ``TypeGuard`` is a type alias for the built-in `bool` type, but it
allows for a single type argument. It is meant to be used to annotate the
return type of a function or method. When it is used in other contexts, it
is treated as a ``bool``.
module. ``TypeGuard`` is a special form that accepts a single type argument.
It is used to annotate the return type of a user-defined type guard function.
Return statements within a type guard function should return bool values,
and type checkers should verify that all return paths return a bool.

In all other respects, TypeGuard is a distinct type from bool. It is not a
subtype of bool. Therefore, ``Callable[..., TypeGuard[int]]`` is not assignable
to ``Callable[..., bool]``.

When ``TypeGuard`` is used to annotate the return type of a function or
method that accepts at least one parameter, that function or method is
assumed by type checkers to be a user-defined type guard. The type argument
treated by type checkers as a user-defined type guard. The type argument
provided for ``TypeGuard`` indicates the type that has been validated by
the function.

Expand All @@ -162,12 +166,13 @@ User-defined type guards can be generic functions, as shown in this example:


Type checkers should assume that type narrowing should be applied to the
expression that is passed as the first explicit argument to a user-defined
expression that is passed as the first positional argument to a user-defined
type guard. If the type guard function accepts more than one argument, no
type narrowing is applied to those additional argument expressions.

If a type guard function is implemented as an instance method or class method,
the first explicit argument maps to the second parameter (after "self" or "cls").
the first positional argument maps to the second parameter (after "self" or
"cls").

Here are some examples of user-defined type guard functions that accept more
than one argument:
Expand All @@ -193,8 +198,8 @@ allows for cases like the example above where ``List[str]`` is not assignable
to ``List[object]``.

When a conditional statement includes a call to a user-defined type guard
function, the expression passed as the first argument to the type guard
function should be assumed by a static type checker to take on the type
function, the expression passed as the first positional argument to the type
guard function should be assumed by a static type checker to take on the type
specified in the TypeGuard return type, unless and until it is further
narrowed within the conditional code block.

Expand Down Expand Up @@ -331,7 +336,7 @@ in PEP 637.
Narrowing of Implicit "self" and "cls" Parameters
-------------------------------------------------

The proposal states that the first explicit argument is assumed to be the
The proposal states that the first positional argument is assumed to be the
value that is tested for narrowing. If the type guard function is implemented
as an instance or class method, an implicit ``self`` or ``cls`` argument will
also be passed to the function. A concern was raised that there may be
Expand Down