I am trying my hand at implementing TypeGuard for mypy. Writing test cases made me wonder what exactly should happen if the type of the argument passed is already subtype of the type in the TypeGuard expression. For example:
def is_nonzero(x: object) -> TypeGuard[float]:
return isinstance(x, float) and x != 0
def main(x: int):
reveal_type(x) # int or float?
Should this *widen* the type of x from int to float? Or should it keep the narrower type int? If we inlined the condition it would keep int, but the way I understand the PEP, it ignores the original type and forces the type in the TypeGuard, in order to support the is_str_list() example.
The PEP does not seem to answer my question directly, since it is mainly concerned with the relationship between the two types in the function definition (arguing convincingly that it should not be a strictly narrowing relationship). I think we had all assumed that the same thing applied to the type of the actual parameter, but having constructed this example I'm not so sure.
Pyright currently reveals float.