@@ -17,6 +17,7 @@ The simplest way to narrow a type is to use one of the supported expressions:
17
17
- :py:func: `isinstance ` like in ``isinstance(obj, float) `` will narrow ``obj `` to have ``float `` type
18
18
- :py:func: `issubclass ` like in ``issubclass(cls, MyClass) `` will narrow ``cls `` to be ``Type[MyClass] ``
19
19
- :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
20
21
21
22
Type narrowing is contextual. For example, based on the condition, mypy will narrow an expression only within an ``if `` branch:
22
23
@@ -57,6 +58,34 @@ We can also use ``assert`` to narrow types in the same context:
57
58
assert isinstance (arg, int )
58
59
reveal_type(arg) # Revealed type: "builtins.int"
59
60
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
+
60
89
Mypy can also use :py:func: `issubclass `
61
90
for better type inference when working with types and metaclasses:
62
91
@@ -75,31 +104,36 @@ for better type inference when working with types and metaclasses:
75
104
reveal_type(t) # Revealed type is "Type[MyCalcMeta]"
76
105
t.calc() # Okay
77
106
78
- .. note ::
107
+ callable
108
+ ~~~~~~~~
79
109
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:
82
112
83
- .. code-block :: python
113
+ .. code-block :: python
84
114
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
89
116
90
- # error: Statement is unreachable
91
- print (" so mypy concludes the assert will always trigger" )
117
+ x: Callable[[], int ]
92
118
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`
95
123
96
- .. code-block :: python
124
+ ``callable `` function can even split ``Union `` type
125
+ for callable and non-callable parts:
97
126
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 ]]
102
132
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"
103
137
104
138
.. _casts :
105
139
0 commit comments