
Jelle Zijlstra wrote:
[...] The motivating use case in the issue was `numpy.isscalar`, which is essentially: def isscalar(element: object) -> TypeGuard[SupportsFloat]: ... In the use case, we have a variable of type `SupportsFloat | numpy.ndarray`, and we want it to narrow to `ndarray` if `isscalar()` returns False. But `isscalar()` returns False on everything that's not a scalar, so we can't just put ndarray as the second argument to TypeGuard. If it existed, we could express it with a type like TypeScript's Exclude ( https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeunion... ): def isscalar(element: T) -> TypeGuard[SupportsFloat, Exclude[T, SupportsFloat]]: ...
You could try something like this: ```py def guard(var: SupportsFloat | T) -> TypeGuard[SupportsFloat, T]: ... def f(x: str | float) -> None: if guard(x): reveal_type(x) # SupportsFloat else: reveal_type(x) # str ``` This does work with the current pyright implementation. Although it is limited to a union of two types for `x`. `str | bytes | float` doesn't work unfortunately.
I'm not sure this is useful in any non-contrived cases. [...] I'm having trouble coming up with a realistic use case for two-parameter TypeGuard other than the NoReturn case that wouldn't need this Exclude type.
Personally, I would love being able to use it for something like `asyncio.iscoroutine` and `asyncio.iscoroutinefunction`. ```py T = TypeVar("T") _T_co = TypeVar("_T_co", covariant=True) _T_contra = TypeVar("_T_contra", contravariant=True) _V_co = TypeVar("_V_co", covariant=True) def iscoroutine(obj: Coroutine[_T_co, _T_contra, _V_co] | T) -> TypeGuard[Coroutine[_T_co, _T_contra, _V_co], T]: ... ```