Consider the following case:
from typing import TypeVarfrom typing_extensions import TypeGuard_T = TypeVar('_T', str, int)def is_str(val: _T) -> TypeGuard[str]: return isinstance(val, str)def is_int(val: _T) -> TypeGuard[int]: return isinstance(val, int)def process_str_int(data: _T) -> _T: if is_str(data): # At this point, `data` is narrowed down to `list[str]` print("Returning a string") return data elif is_int(data): print("Returning an int") return datadef process_str_int_with_isinstance(data: _T) -> _T: if isinstance(data, str): # At this point, `data` is narrowed down to `list[str]` print("Returning a string") return data elif isinstance(data, int): print("Returning an int") return dataprocess_str_int("hello")At the point of return in process_str_int I get an error in pyright complaining that 'Expression of type "str" cannot be assigned to return type "_T@process_list"' (and similarly for the int case). The python interpreter is python 3.9
This does not happen with isinstance, where the TypeVar is correctly narrowed down and thus the correct return type is inferred and matched against the return value
How can I acheive a similar behaviour using custom type guards?