-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PEP647 typing.TypeGuard based is_ok() and is_err() helpers #69
Comments
I can only speak briefly about this as I do more TypeScript work than Python (very little Python actually). In TS it's very common to use typeguards and providing a more descriptive and terser |
first investigation shows that mypy may have some issues in this area; i've reported python/mypy#11428 about that. |
If only older Python versions need it, I don't think adding a dependency is a problem. By upgrading your Python, you can get rid of the dependency. We did the same thing with From my experience with TS, type guards are pretty nice to have. |
It seems like mypy generic typeguards are fixed, but there's still no negation. from result import Ok, Result
from typing import TypeVar
from typing_extensions import TypeGuard
E = TypeVar("E")
T = TypeVar("T")
def is_ok(result: Result[T, E]) -> TypeGuard[Ok[T]]:
return isinstance(result, Ok)
def main(result: Result[str, int]):
if is_ok(result):
reveal_type(result)
else:
reveal_type(result)
Doing something like this would work: def main(result: Result[str, int]):
if is_ok(result):
reveal_type(result)
elif is_err(result):
reveal_type(result)
...but ideally we wouldn't need to do this. Related discussion for typeguard negations: python/typing#1013 |
@qexat as @jack-michaud touches upon, we'd need a |
Although it's not possible to do it using from __future__ import annotations
import typing as t
from typing_extensions import Literal, TypeAlias
from result import Ok as _Ok, Err as _Err
T = t.TypeVar("T")
E = t.TypeVar("E")
class Ok(_Ok[T]):
def __bool__(self) -> Literal[True]:
return True
class Err(_Err[E]):
def __bool__(self) -> Literal[False]:
return False
Result: TypeAlias = "Ok[T] | Err[E]"
def foo(ok_t: t.Type[T], err_t: t.Type[E]) -> Result[T, E]:
raise NotImplementedError
x = foo(int, Exception)
reveal_type(x)
if x:
reveal_type(x)
else:
reveal_type(x) src/synopsys/tasks/result.py:31:13: note: Revealed type is "Union[synopsys.tasks.result.Ok[builtins.int], synopsys.tasks.result.Err[builtins.Exception]]"
src/synopsys/tasks/result.py:34:17: note: Revealed type is "synopsys.tasks.result.Ok[builtins.int]"
src/synopsys/tasks/result.py:36:17: note: Revealed type is "synopsys.tasks.result.Err[builtins.Exception]" It eliminates the need for |
Hey, just stumbled upon the lib yesterday and immediately thought of type guards. Wonder if there is any particular reason it hasn't been done yet? Should be a pretty simple PR, happy to contribute if this just a matter of lack of time. P.S. I wish the PEP didn't drop the |
@mishamsk You're welcome to help out with PRs :) |
update changelog & docs add typeguard mypy tests
PEP 647 (https://www.python.org/dev/peps/pep-0647/) makes it possible to write custom type guard functions.
this makes it possible to write shorthand
is_ok(...)
andis_err(...)
functions that effectively work as shorthands for the longerisinstance(..., ...)
forms, resulting in denser and more readable code, while still keeping all the benefits of strict type checking:not all supported python versions support
TypeGuard
, but the widely usedtyping_extensions
package (https://github.com/python/typing/blob/master/typing_extensions/README.rst) has a functional backport that works with (at least) mypy. i personally do not see a problem adding a dependency ontyping_extensions
, since it's maintained ‘upstream’, close to python itself, and it will already be pulled in by many other libraries in many real-world applications.thoughts? opinions? (cc @francium @dbrgn)
The text was updated successfully, but these errors were encountered: