@@ -17,6 +17,7 @@ The simplest way to narrow a type is to use one of the supported expressions:
1717- :py:func: `isinstance ` like in ``isinstance(obj, float) `` will narrow ``obj `` to have ``float `` type
1818- :py:func: `issubclass ` like in ``issubclass(cls, MyClass) `` will narrow ``cls `` to be ``Type[MyClass] ``
1919- :py:func: `type ` like in ``type(obj) is int `` will narrow ``obj `` to have ``int `` type
20+ - :py:func: `callable ` like in ``callable(obj) `` will narrow object to callable type
2021
2122Type narrowing is contextual. For example, based on the condition, mypy will narrow an expression only within an ``if `` branch:
2223
@@ -57,6 +58,34 @@ We can also use ``assert`` to narrow types in the same context:
5758 assert isinstance (arg, int )
5859 reveal_type(arg) # Revealed type: "builtins.int"
5960
61+ .. note ::
62+
63+ With :option: `--warn-unreachable <mypy --warn-unreachable> `
64+ narrowing types to some impossible state will be treated as an error.
65+
66+ .. code-block :: python
67+
68+ def function (arg : int ):
69+ # error: Subclass of "int" and "str" cannot exist:
70+ # would have incompatible method signatures
71+ assert isinstance (arg, str )
72+
73+ # error: Statement is unreachable
74+ print (" so mypy concludes the assert will always trigger" )
75+
76+ Without ``--warn-unreachable `` mypy will simply not check code it deems to be
77+ unreachable. See :ref: `unreachable ` for more information.
78+
79+ .. code-block :: python
80+
81+ x: int = 1
82+ assert isinstance (x, str )
83+ reveal_type(x) # Revealed type is "builtins.int"
84+ print (x + ' !' ) # Typechecks with `mypy`, but fails in runtime.
85+
86+ issubclass
87+ ~~~~~~~~~~
88+
6089Mypy can also use :py:func: `issubclass `
6190for better type inference when working with types and metaclasses:
6291
@@ -75,31 +104,36 @@ for better type inference when working with types and metaclasses:
75104 reveal_type(t) # Revealed type is "Type[MyCalcMeta]"
76105 t.calc() # Okay
77106
78- .. note ::
107+ callable
108+ ~~~~~~~~
79109
80- With :option: ` --warn-unreachable <mypy --warn-unreachable> `
81- narrowing types to some impossible state will be treated as an error.
110+ Mypy knows what types are callable and which ones are not during type checking.
111+ So, we know what `` callable() `` will return. For example:
82112
83- .. code-block :: python
113+ .. code-block :: python
84114
85- def function (arg : int ):
86- # error: Subclass of "int" and "str" cannot exist:
87- # would have incompatible method signatures
88- assert isinstance (arg, str )
115+ from typing import Callable
89116
90- # error: Statement is unreachable
91- print (" so mypy concludes the assert will always trigger" )
117+ x: Callable[[], int ]
92118
93- Without ``--warn-unreachable `` mypy will simply not check code it deems to be
94- unreachable. See :ref: `unreachable ` for more information.
119+ if callable (x):
120+ reveal_type(x) # N: Revealed type is "def () -> builtins.int"
121+ else :
122+ ... # Will never be executed and will raise error with `--warn-unreachable`
95123
96- .. code-block :: python
124+ ``callable `` function can even split ``Union `` type
125+ for callable and non-callable parts:
97126
98- x: int = 1
99- assert isinstance (x, str )
100- reveal_type(x) # Revealed type is "builtins.int"
101- print (x + ' !' ) # Typechecks with `mypy`, but fails in runtime.
127+ .. code-block :: python
128+
129+ from typing import Callable, Union
130+
131+ x: Union[int , Callable[[], int ]]
102132
133+ if callable (x):
134+ reveal_type(x) # N: Revealed type is "def () -> builtins.int"
135+ else :
136+ reveal_type(x) # N: Revealed type is "builtins.int"
103137
104138 .. _casts :
105139
0 commit comments