Currently, typeshed annotates
def callable(obj: object, /) -> TypeIs[Callable[..., object]]: ...
However, for the majority of type checkers this creates discrepancy between collections.abc.Callable and builtins.callable narrowing, only ty seems to consider blank Callable as if it were Callable[..., object], whereas all other type checkers treat it as Callable[..., Any].
from typing import reveal_type, TypeIs
from collections.abc import Callable
def is_callable(arg: object) -> TypeIs[Callable]:
raise NotImplementedError
def check_callable(arg: object) -> None:
if isinstance(arg, Callable):
reveal_type(arg)
def check_callable2(arg: object) -> None:
if callable(arg):
reveal_type(arg)
def check_callable3(arg: object) -> None:
if is_callable(arg):
reveal_type(arg)
| case |
isinstance(x, Callable) |
is_callable |
callable(x) |
| mypy |
ERROR |
(...) -> Any |
<callable subtype of object> |
| pyright |
(...) -> Unknown |
(...) -> Unknown |
(...) -> object |
| pyrefly |
(...) -> Unknown |
(...) -> Unknown |
(...) -> object |
| ty |
(...) -> object |
(...) -> Any |
(...) -> object |
| zuban |
ERROR |
(...) -> Any |
<callable subtype of object> |
Currently, typeshed annotates
However, for the majority of type checkers this creates discrepancy between
collections.abc.Callableandbuiltins.callablenarrowing, onlytyseems to consider blankCallableas if it wereCallable[..., object], whereas all other type checkers treat it asCallable[..., Any].