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

More typed arguments in withLatestFrom #5221

Closed
jnorkus opened this issue Jan 7, 2020 · 9 comments
Closed

More typed arguments in withLatestFrom #5221

jnorkus opened this issue Jan 7, 2020 · 9 comments

Comments

@jnorkus
Copy link

jnorkus commented Jan 7, 2020

Feature Request

Is your feature request related to a problem? Please describe.
Currently the max number of supported arguments in withLatestFrom is 5. Adding more than that results in any types.

Describe the solution you'd like
Add more function exports to the withLatestFrom.ts.

I'll gladly create a PR if above is an accepted solution.

@cartant
Copy link
Collaborator

cartant commented Jan 7, 2020

I'm in two minds about adding more signatures, at this stage. Version 7 is currently being worked on and the focus of that version is improving the types - as we'll no longer be constrained by having to support TypeScript 2.8.

See #5066

On of the principal aims will be to solve this needs-more-args problem once and for all - by having signatures that support an arbitrary number of arguments.

That said, if withLastestFrom has fewer typed arguments than most of the other signatures, I wouldn't be opposed to adding more to bring it into line. If they all have five typed arguments, I think we should just leave it as is. TBH, I think more than five arguments to withLastestFrom is pretty edge-case-y.

@jnorkus
Copy link
Author

jnorkus commented Jan 7, 2020

Thanks for the explanation and pointing to the existing issue. Hopefully it will get better in v7.

However I don't think having more arguments is "edge-case-y" - it really depends on complexity of the application. In my case I have multiple UI components collecting input from user across a wizard-like steps. I use withLatestFrom to aggregate all of this data into a single request. Are there better ways of doing it? I could probably extract that into selectors (ngrx) but I would only do this to work around the typing issue.

@cartant
Copy link
Collaborator

cartant commented Jan 7, 2020

Well, I'm not saying it's wrong. I'm just saying that it's an edge case and I think this being the first time the issue has been raised - AFAICT - in a number of years attests to that.

Anyway, if you want, you can take advantage of TypeScript's declaration merging to add signatures with more typed parameters in userland. You should be able to add as many as you need - while you wait for v7 - by doing something like this:

declare module "rxjs/internal/operators/withLatestFrom" {
  export declare function withLatestFrom<
    T,
    O2 extends ObservableInput<any>,
    O3 extends ObservableInput<any>,
    O4 extends ObservableInput<any>,
    O5 extends ObservableInput<any>,
    O6 extends ObservableInput<any>,
    O7 extends ObservableInput<any>
  >(
    v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, v7: O7
  ): OperatorFunction<T, [
    T,
    ObservedValueOf<O2>,
    ObservedValueOf<O3>,
    ObservedValueOf<O4>,
    ObservedValueOf<O5>,
    ObservedValueOf<O6>,
    ObservedValueOf<O7>
  ]>;
}

@jnorkus
Copy link
Author

jnorkus commented Jan 7, 2020

This is a perfect workaround for now. Thanks!

@jnorkus
Copy link
Author

jnorkus commented Jan 7, 2020

Update:
I haven't been able to make this work as suggested, by merging definitions. Doing as suggested overwrites the definitions so Typescript only sees the declarations for that module in my typings.d.ts. Adding an export to declare module fixed the issue and now they are merged but then it stills shows any type as the output for some reason, even though it identifies the signature correctly. Not sure if I'm missing something or it's Typescript.

I ended up copying all of the signatures from withLatestFrom.d.ts to my typings.d.ts and also adding the extensions. I also have to import using the full path (i.e. import { withLatestFrom } from 'rxjs/internal/operators/withLatestFrom';) and can't do a import { withLatestFrom } from 'rxjs/operators';. Now it seems to work.

@cartant
Copy link
Collaborator

cartant commented Jan 7, 2020

I would not have put it in a .d.ts file. I would have put the snippet into a .ts file.

@cartant
Copy link
Collaborator

cartant commented Jan 7, 2020

@cartant
Copy link
Collaborator

cartant commented Jan 8, 2020

I've had time to try it and this seems to be fine for me - with RxJS 6.5.4 and TypeScript 3.7.4:

import { ObservableInput, ObservedValueOf, of, OperatorFunction } from "rxjs";
import { withLatestFrom } from "rxjs/operators";

declare module "rxjs/internal/operators/withLatestFrom" {
  export function withLatestFrom<
    T,
    O2 extends ObservableInput<any>,
    O3 extends ObservableInput<any>,
    O4 extends ObservableInput<any>,
    O5 extends ObservableInput<any>,
    O6 extends ObservableInput<any>,
    O7 extends ObservableInput<any>
  >(
    v2: O2,
    v3: O3,
    v4: O4,
    v5: O5,
    v6: O6,
    v7: O7
  ): OperatorFunction<
    T,
    [
      T,
      ObservedValueOf<O2>,
      ObservedValueOf<O3>,
      ObservedValueOf<O4>,
      ObservedValueOf<O5>,
      ObservedValueOf<O6>,
      ObservedValueOf<O7>
    ]
  >;
}

const source = of(1).pipe(
  withLatestFrom(of(2), of(3), of(4), of(5), of(6), of(7))
);

@cartant
Copy link
Collaborator

cartant commented Jan 8, 2020

Closing this, as it's going to be addressed in v7 and there is a userland workaround.

if you have problems with the workaround, feel free to comment in this issue, though.

@cartant cartant closed this as completed Jan 8, 2020
@lock lock bot locked as resolved and limited conversation to collaborators Feb 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants