Synopsys
beartype.door.is_bearable cannot be used for type narrowing with mypy or pyright as described in the documentation, due to an incorrect type annotation.
To Reproduce
Both mypy and pyright show type errors with this example from the Beartype documentation:
from beartype.door import is_bearable
def narrow_types_like_a_boss_with_beartype(lst: list[int | str]):
if is_bearable(lst, list[int]):
munch_on_list_of_integers(lst)
elif is_bearable(lst, list[str]):
munch_on_list_of_strings(lst)
def munch_on_list_of_strings(lst: list[str]): ...
def munch_on_list_of_integers(lst: list[int]): ...
Result from mypy:
$ mypy ./bug.py
bug.py:5: error: Argument 1 to "munch_on_list_of_integers" has incompatible type "Type[List[Any]]"; expected "List[int]" [arg-type]
bug.py:7: error: Argument 1 to "munch_on_list_of_strings" has incompatible type "Type[List[Any]]"; expected "List[str]" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
Result from pyright:
$ pyright ./bug.py
[elided]/bug.py
[elided]/bug.py:5:35 - error: Argument of type "type[list[int]]" cannot be assigned to parameter "lst" of type "list[int]" in function "munch_on_list_of_integers"
"type[type]" is incompatible with "type[list[int]]" (reportGeneralTypeIssues)
[elided]/bug.py:7:34 - error: Argument of type "type[list[str]]" cannot be assigned to parameter "lst" of type "list[str]" in function "munch_on_list_of_strings"
"type[type]" is incompatible with "type[list[str]]" (reportGeneralTypeIssues)
2 errors, 0 warnings, 0 informations
Expected behavior
mypy and pyright should show no errors when type-checking the code.
Extra notes
The type signature of is_bearable is as follows from the source code:
def is_bearable(
obj: object,
hint: T,
*,
conf: BeartypeConf = BEARTYPE_CONF_DEFAULT,
) -> TypeGuard[T]:
...
For example, if the user calls is_bearable(some_variable, int), then T is bound as type[int] instead of int, since T has to be the type of whatever argument was passed in (which was int). Thus, static type checkers now believe that some_variable has the type type[int] instead of the correct int.
This can can be fixed by a simple change to the type signature:
def is_bearable(
obj: object,
hint: type[T],
*,
conf: BeartypeConf = BEARTYPE_CONF_DEFAULT,
) -> TypeGuard[T]:
...
Now, when is_bearable(some_variable, int) is called, T will be assigned to int, and so some_variable will be correctly identified as having type int instead of type[int].
Unfortunately, this change seems to break type checking on other parts of the code (namely beartype.door._cls.super.TypeHint). I'm not sure how these other type hints should be corrected, which is why I submitted an issue instead of a PR. If anyone reviewing this issue has any guidance on how any other type annotations should be modified, I would be happy to attempt a PR again to fix this issue.
Synopsys
beartype.door.is_bearablecannot be used for type narrowing withmypyorpyrightas described in the documentation, due to an incorrect type annotation.To Reproduce
Both
mypyandpyrightshow type errors with this example from the Beartype documentation:Result from
mypy:Result from
pyright:Expected behavior
mypyandpyrightshould show no errors when type-checking the code.Extra notes
The type signature of
is_bearableis as follows from the source code:For example, if the user calls
is_bearable(some_variable, int), thenTis bound astype[int]instead ofint, sinceThas to be the type of whatever argument was passed in (which wasint). Thus, static type checkers now believe thatsome_variablehas the typetype[int]instead of the correctint.This can can be fixed by a simple change to the type signature:
Now, when
is_bearable(some_variable, int)is called,Twill be assigned toint, and sosome_variablewill be correctly identified as having typeintinstead oftype[int].Unfortunately, this change seems to break type checking on other parts of the code (namely
beartype.door._cls.super.TypeHint). I'm not sure how these other type hints should be corrected, which is why I submitted an issue instead of a PR. If anyone reviewing this issue has any guidance on how any other type annotations should be modified, I would be happy to attempt a PR again to fix this issue.