The example you propose is not the same as mine because my original takes any object, and narrows to float only if it's float and nonzero.

But I am fine having my proposal rejected -- as long as you update the PEP to (1) make explicit that the assumed type is always exactly what is inferred from the type guard (or however you want to formulate that) and (2) add my suggestion to the rejected ideas, with the explanation you just gave (that the rule would have to be more complex because of certain things, and it's too complicated for little or no extra value).

On Wed, Dec 30, 2020 at 11:46 AM Eric Traut <> wrote:
You can definitely use type variables within a type guard function. The PEP already contains a couple of examples of that. Here's how I'd recommend modifying your sample. Note that there's no need for a union type or an `isinstance` check because of the use of the bound TypeVar.

T = TypeVar("T", bound=float)
def is_nonzero(x: T) -> TypeGuard[T]:
    return x != 0

a = 3
if is_nonzero(a):
    reveal_type(a)  # int

b = 3.14
if is_nonzero(b):
    reveal_type(b)  # float

This example is a bit contrived in that "non-zeroness" isn't captured by the type indicated by the TypeGuard, so there's nothing of value a static type checker can do with the information provided by this type guard function.

I don't think we should apply the conditional rule you proposed. The rule would have to be more complex than what you stated to handle unions and constrained TypeVars (which are similar to unions). The rule adds complexity in terms of the implementation but more importantly in the mental model for the user. It would introduce an inconsistency while providing little or no additional value. If you think it's advisable to add a new section to the PEP, I can do so.
Typing-sig mailing list --
To unsubscribe send an email to
Member address:

--Guido van Rossum (
Pronouns: he/him (why is my pronoun here?)