You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to make a function called ensure that takes a type guard function and an argument and returns the argument if the type guard function returns true:
defensure(guard: Callable[[X], TypeGuard[Y]], x: X) ->Y:
ifguard(x):
returnxraiseTypeError(f'{x} is not the right type')
This works fine for simple Union types, but fails for recursive Union types. Both scenarios work fine in Pylance.
that repros the issue. (It is also a valid pytest test.)
The core of the issue is shown by:
Y=TypeVar('Y')
Foo: TypeAlias=list['Foo'] |str|intdefis_str(o: Foo) ->TypeGuard[str]:
returnisinstance(o, str)
defensure(guard: Callable[[Foo], TypeGuard[Y]], x: Foo) ->Y:
ifguard(x):
returnxraiseTypeError(f'{x} is not the right type')
deftest_ensure_is_str(s: Foo) ->None:
# Pylance: list[Foo] | str | int; mypy: Union[builtins.list[...], builtins.str, builtins.int]reveal_type(s)
# mypy: error: Need type annotation for "x" [var-annotated]# mypy: error: Argument 1 to "ensure" has incompatible type "Callable[[Foo], TypeGuard[str]]"; expected "Callable[[Foo], TypeGuard[Never]]" [arg-type]x=ensure(is_str, s)
reveal_type(x) # Pylance: str; mypy: Any# error: Argument 1 to "ensure" has incompatible type "Callable[[Foo], TypeGuard[str]]"; expected "Callable[[Foo], TypeGuard[Never]]" [arg-type]reveal_type(ensure(is_str, s)) # Pylance: str; mypy: Neverassertx==s
In this example, mypy can't deduce that x is a str because it expects ensure to take a function returning TypeGuard[Never].
Expected Behavior
mypy should be able to:
correctly deduce the argument type to ensure
deduce that x is a str
Actual Behavior
main.py:32: note: Revealed type is "Union[builtins.list[...], builtins.str, builtins.int]"
main.py:35: error: Need type annotation for "x" [var-annotated]
main.py:35: error: Argument 1 to "ensure" has incompatible type "Callable[[Foo], TypeGuard[str]]"; expected "Callable[[Foo], TypeGuard[Never]]" [arg-type]
main.py:36: note: Revealed type is "Any"
main.py:38: note: Revealed type is "Never"
main.py:38: error: Argument 1 to "ensure" has incompatible type "Callable[[Foo], TypeGuard[str]]"; expected "Callable[[Foo], TypeGuard[Never]]" [arg-type]
Your Environment
Mypy version used: 1.14.1
Mypy command-line flags: none
Mypy configuration options from mypy.ini (and other config files): none
Python version used: 3.11, 3.12
The text was updated successfully, but these errors were encountered:
Bug Report
I'm trying to make a function called
ensure
that takes a type guard function and an argument and returns the argument if the type guard function returns true:This works fine for simple Union types, but fails for recursive Union types. Both scenarios work fine in Pylance.
To Reproduce
I created a Gist at:
https://mypy-play.net/?mypy=latest&python=3.12&gist=b48835cb0b0a7a3b5933e10593107dd3
that repros the issue. (It is also a valid pytest test.)
The core of the issue is shown by:
In this example, mypy can't deduce that
x
is astr
because it expectsensure
to take a function returningTypeGuard[Never]
.Expected Behavior
mypy should be able to:
ensure
x
is astr
Actual Behavior
Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: