Hm... I wish it were true, but I've got a feeling that the example in PEP 586 may be wrong. The way the overload is written, it may still return True from the second overload, so we cannot prove that just because the function returns True, the argument must be of type int. And changing the second overload to `-> Literal[False]` provokes another reasonable error message: "Overloaded function signatures 1 and 2 overlap with incompatible return types".
On Tue, Nov 24, 2020 at 7:17 PM David Foster email@example.com wrote:
Unfortunately, that doesn't provide the desired affect.
Based on PEP 586 §"Interactions with narrowing" it appears that the syntax mentioned by Ivan Levkivskyi is *supposed* to work, even though mypy (and pyright?) don't appear to implement it.
If I copy the example from PEP 586, with minimal changes, and typecheck it with mypy and reveal_type():
from typing import * @overload def is_int_like(x: Union[int, List[int]]) -> Literal[True]: ... @overload def is_int_like(x: object) -> bool: ... def is_int_like(x): ... def foo(scalar: Union[int, str]) -> None: if is_int_like(scalar): reveal_type(scalar) # mypy says: Revealed type is 'Union[
builtins.int, builtins.str]' scalar += 3 # PEP says: Type checks: type of 'scalar' is narrowed to 'int' else: reveal_type(scalar) # mypy says: Revealed type is 'Union[ builtins.int, builtins.str]' scalar += "foo" # PEP says: Type checks: type of 'scalar' is narrowed to 'str'
Notice the annotations in the comments.
So one might argue that mypy/pyright should be updated to support the "returns Literal[True]" pattern put forward by PEP 586.
I *do* think the TypeGuard-based syntax is easier to understand and more-straightforward than implementing an overload that returns Literal[True]. It will also be easier for folks coming from TypeScript background to understand since there's a direct analogue for TypeGuard in TypeScript.
-- David Foster | Seattle, WA, USA Contributor to TypedDict support for mypy _______________________________________________ Typing-sig mailing list -- firstname.lastname@example.org To unsubscribe send an email to email@example.com https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: firstname.lastname@example.org