Skip to content
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

Handle type guards properly in Receiver.filter() #332

Open
wants to merge 1 commit into
base: v1.x.x
Choose a base branch
from

Conversation

llucax
Copy link
Contributor

@llucax llucax commented Nov 14, 2024

Now the Receiver type returned by Receiver.filter() will have the narrowed type when a TypeGuard is used.

Now the `Receiver` type returned by `Receiver.filter()` will have the
narrowed type when a `TypeGuard` is used.

Signed-off-by: Leandro Lucarella <[email protected]>
@llucax llucax requested a review from a team as a code owner November 14, 2024 13:06
@llucax llucax self-assigned this Nov 14, 2024
@github-actions github-actions bot added part:docs Affects the documentation part:tests Affects the unit, integration and performance (benchmarks) tests part:core Affects the core types (`Sender`, `Receiver`, exceptions, etc.) labels Nov 14, 2024
Comment on lines +319 to +327
# We need to use Any here because otherwise _Filter would have to deal with two
# different signatures. We can create two filter classes, one for regular functions
# and one for type guards, but then there is no way to tell at runtime which
# function is a type guard and which isn't to instantiate the correct class.
# Using Any here has no impact though, as thanks to the overloads, only the
# overloaded types will be accepted.
def filter(
self, filter_function: Callable[[ReceiverMessageT_co], Any], /
) -> Receiver[Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to change _Filter because TypeGuard is just another name for bool, with some additional semantic meaning. The type system knows assigning a TypeGuard value to a bool is fine.

Suggested change
# We need to use Any here because otherwise _Filter would have to deal with two
# different signatures. We can create two filter classes, one for regular functions
# and one for type guards, but then there is no way to tell at runtime which
# function is a type guard and which isn't to instantiate the correct class.
# Using Any here has no impact though, as thanks to the overloads, only the
# overloaded types will be accepted.
def filter(
self, filter_function: Callable[[ReceiverMessageT_co], Any], /
) -> Receiver[Any]:
def filter(
self,
filter_function: (
Callable[[ReceiverMessageT_co], bool]
| Callable[[ReceiverMessageT_co], TypeGuard[FilteredMessageT_co]]
),
/,
) -> Receiver[ReceiverMessageT_co] | Receiver[FilteredMessageT_co]:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
part:core Affects the core types (`Sender`, `Receiver`, exceptions, etc.) part:docs Affects the documentation part:tests Affects the unit, integration and performance (benchmarks) tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants