# Compatibility between TypeGuard and bool

**URL:** <https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364>\
**Category:** Typing\
**Tags:** typing-spec\
**Created:** [February 19, 2024, 7:31pm UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364 "2024-02-19T19:31:55Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [February 19, 2024, 7:31pm UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364/1 "2024-02-19T19:31:55Z")

</div>

The typing spec [currently states](https://typing.readthedocs.io/en/latest/spec/narrowing.html#typeguard):

> [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:

```python
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](https://mypy-play.net/?mypy=latest&python=3.10&gist=be1f9540308db62afb7b2b7b5f49f19e) and [pyright](https://pyright-play.net/?pythonVersion=3.12&code=GYJw9gtgBAlgLgUxHMYA2BnWEAOZlQDGYArgHZwCwAUKJFHAJ44xkDm2eBAKswgOIkAhiAAmAGigBhIWjRCARmgSSAkohCLlNGqITAowGGg0JRAfWLk4AChwgzALmmz5ShAG0PrOAF1JCqhovgCUUAC0AHxQ6khanj6%2BjjRQqYb4sLBkRKQUNiHJ1GnFsAb2ZjYwBSkltYwwCGiisDrUegYwGOYIAG4IZOY%2BNgAezmAKAFYIhHBhUVC8OALCYt4USTWpDnAkINmdrBhwQmSECCOSPmEnzcNQAKRQAExQALyvUAAMrcAZMFmGYymCxWPKdbp9AZXQrFexDKo0IA) 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](https://github.com/python/peps/pull/1765). @erictraut [told me](https://github.com/python/peps/pull/3649#discussion_r1483855777) 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](https://discuss.python.org/t/pep-742-narrowing-types-with-typeis/45613). 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.

---

<div class="post-metadata">

**Author:** ![erictraut](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/erictraut/32/15190_2.png) [@erictraut](https://discuss.python.org/u/erictraut)\
**Post date:** [February 19, 2024, 7:52pm UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364/2 "2024-02-19T19:52:15Z")

</div>

I’m in favor of your proposed change.

---

<div class="post-metadata">

**Author:** ![guido](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/guido/32/21_2.png) [@guido](https://discuss.python.org/u/guido)\
**Post date:** [February 19, 2024, 9:20pm UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364/3 "2024-02-19T21:20:35Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [February 21, 2024, 1:21pm UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364/4 "2024-02-21T13:21:38Z")

</div>

I have posted a proposed spec/test suite change:

> <https://github.com/python/typing/pull/1637>
>
> See https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364

And an issue for the Typing Council:

> <https://github.com/python/typing-council/issues/20>
>
> Please review this proposed spec change about compatibility between TypeGuard an…d bool: https://github.com/python/typing/pull/1637. All four major type checkers already conform with the proposed change. Previous discussion thread on https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364.
> 
> \*\*TC Sign-off\*\*
> \* \[\] Eric
> \* \[\] Guido
> \* \[x\] Jelle
> \* \[\] Rebecca
> \* \[\] Shantanu

---

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [February 29, 2024, 12:32am UTC](https://discuss.python.org/t/compatibility-between-typeguard-and-bool/46364/5 "2024-02-29T00:32:05Z")

</div>

The Typing Council has [accepted](https://github.com/python/typing-council/issues/20) this change and I [merged](https://github.com/python/typing/pull/1637) the change into the spec. Thanks everyone!

Next, I’ll update PEP 742 to match.
