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

fromEventPattern() should not magically return different results based on arguments.length #4736

Open
felixfbecker opened this issue Apr 26, 2019 · 4 comments

Comments

@felixfbecker
Copy link
Contributor

felixfbecker commented Apr 26, 2019

Bug Report

Current Behavior
fromEventPattern currently checks args.length and if it's 1, emits the first item, otherwise it emits an array of all:

const handler = (...e: T[]) => subscriber.next(e.length === 1 ? e[0] : e);

This is problematic because it is not type safe and unpredictable.
It could be made slightly more type safe with a conditional type, but even then, if the parameter is optional TS would accept calling the listener with undefined or no parameter at all, which are different args.length and would result in one case in the emission of an array [undefined] and in the other case in undefined, which would not be checked by the type checker.

Checking arguments.length is generally considered bad practice.

What's worse is that you can't even reliably use resultSelector anymore to ensure it is always an array, because the magic switching is always done first, and resultSelector is just a shortcut now that checks if the element is an array. Which means that if the listener was actually called with an array as a single parameter, the resultSelector logic would think it was instead called with multiple parameters and spread the array out.

Expected behavior
fromEventPattern() should just emit a tuple of all parameters. It's trivial to destructure that array or map it to just the first parameter if desired.

Environment

  • RxJS version: 6
@cartant
Copy link
Collaborator

cartant commented Apr 26, 2019

Yeah. I agree that this behaviour is not ideal. This is something that could be looked at for v7, but not for v6 where it would be a breaking change.

@thorn0
Copy link
Contributor

thorn0 commented Jun 10, 2019

How about simply replacing e.length === 1 with e.length <= 1 for now? I'd call it a bug fix, not a breaking change.

@benlesh
Copy link
Member

benlesh commented Mar 31, 2021

Maybe with all of the functions that do this (bindCallback and friends also do this), we could return the result selector, and just the result collector gets args[] but the default, without the result selector will always just be the first argument.

So, let's say your fromEvent source has 3 args: number, string, boolean: fromEvent(thing, 'whatever') would return Observable<number> always. BUT, fromEvent(thing, 'whatever', (a: number, b: string, c: boolean) => of([a, b, c])) would give you Observable<[number, string, boolean]>.

It's an idea. Of course, we'd need to wait a long time to introduce this, because it's a breaking change.

@benlesh benlesh added AGENDA ITEM Flagged for discussion at core team meetings and removed type: discussion labels Mar 31, 2021
@benlesh
Copy link
Member

benlesh commented Apr 21, 2021

Core Team Notes: Punting this change to version 8. We can't do this at this stage of the v7 release. This will also give us time to come up with a solid design for how to handle this.

@benlesh benlesh removed the AGENDA ITEM Flagged for discussion at core team meetings label Apr 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants