Compatibility between TypeGuard and bool

The typing spec currently states:

[TypeGuard] is not a subtype of bool. Therefore, Callable[..., TypeGuard[int]] is not assignable to Callable[..., bool] .

That means that the following program should be rejected by type checkers:

from itertools import count
from typing import TypeGuard, Callable, Iterable

def filtered_count(pred: Callable[[int], bool]) -> Iterable[int]:
    for i in count():
        if pred(i):
            yield i

def is_even_int(x: object) -> TypeGuard[int]:
    return isinstance(x, int) and x % 2 == 0

for i in filtered_count(is_even_int):
    print(i)

This is passing a function returning a TypeGuard to a parameter of type Callable[[int], bool], and the spec explicitly says that is not allowed.

However, both mypy and pyright accept this program without errors. It works fine at runtime, and I donā€™t see any soundness problems that result from accepting it.

The rule in the spec derives from PEP 647 (which created TypeGuard) and was added in this PR. @erictraut told me that the change derived from feedback by Guido, but I havenā€™t been able to find a more precise motivation.

I propose to change the spec so that Callable[..., TypeGuard[...]] is a subtype of Callable[..., bool]. This brings the spec in line with the actual behavior of major type checkers.

The same reasoning applies to the new TypeIs special form I propose in PEP 742. For the moment I copied the TypeGuard restriction in the new PEP, but if the proposal in this post is accepted, Iā€™ll change PEP 742 accordingly.

13 Likes

Iā€™m in favor of your proposed change.

Iā€™m also in favor. Regarding my original objection, itā€™s possible that I objected to TypeGuard[...] being considered a subtype of bool everywhere, rather than in the specific case where itā€™s the return type of a Callable type. FWIW, in my recollection I wasnā€™t the one who originally came up with this argument, but (a) memory is fungible, and (b) it doesnā€™t matter assuming we all agree on this now.

I have posted a proposed spec/test suite change:

And an issue for the Typing Council:

The Typing Council has accepted this change and I merged the change into the spec. Thanks everyone!

Next, Iā€™ll update PEP 742 to match.

2 Likes