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

Return type of selectQueryParam is incorrect #4286

Open
1 of 2 tasks
Tezra opened this issue Apr 1, 2024 · 2 comments
Open
1 of 2 tasks

Return type of selectQueryParam is incorrect #4286

Tezra opened this issue Apr 1, 2024 · 2 comments

Comments

@Tezra
Copy link

Tezra commented Apr 1, 2024

Which @ngrx/* package(s) are the source of the bug?

router-store

Minimal reproduction of the bug/regression with instructions

Sorry I can't provide a minimal example, but for some reason my StackBlitz example always returns undefined (https://stackblitz.com/edit/angular-63sasz?file=src%2Fapp%2Fmy-counter%2Fmy-counter.component.ts, incase you can fix the configuration). This bug is a discrepancy between the static and runtime typing though. (example snippet below).

The selector from selectQueryParam says the return type is string, however the actual type at runtime is string[] | string | undefined, based on if the query param appears 0 (undefined), 1 (string) or more (string[]) times.

import { Component } from '@angular/core';
import { RouterReducerState } from '@ngrx/router-store';
import { Store, select, createFeatureSelector } from '@ngrx/store';
import { Observable } from 'rxjs';
import * as RouteStore from '@ngrx/router-store';
import { tap } from 'rxjs/operators';

export const {
  selectCurrentRoute, // select the current route
  selectQueryParams, // select the current route query params
  selectQueryParam, // factory function to select a query param
  selectRouteParams, // select the current route params
  selectRouteParam, // factory function to select a route param
  selectRouteData, // select the current route data
  selectUrl, // select the current url
} = RouteStore.getRouterSelectors(
  createFeatureSelector<RouterReducerState>('router')
);
const aSelector = selectQueryParam('a');
const bSelector = selectQueryParam('b');

@Component({
  selector: 'app-my-counter',
  templateUrl: './my-counter.component.html',
  styleUrls: ['./my-counter.component.css'],
})
export class MyCounterComponent {
  a$: Observable<string>; // Actually Observable<string[] | string | undefined>
  b$: Observable<string>;

  constructor(private store: Store<any>) {
    this.a$ = this.store.pipe(select(aSelector), tap(console.log));
    this.b$ = this.store.pipe(select(bSelector), tap(console.log));
  }
}

Expected behavior

For the runtime type to match the Typescript type.

Versions of NgRx, Angular, Node, affected browser(s) and operating system(s)

As far as I can tell, all.

Other information

Fixing this would be a breaking change, but the incorrect type is an issue for strict projects trying to take advantage of the string[] behavior, and if the url is modified in an unexpected way, may crash pages that think they are type safe.

I would be willing to submit a PR to fix this issue

  • Yes
  • No
@timdeschryver
Copy link
Member

Hi, it seems like you're right!
Do you want to create a PR for this?
We can schedule this for v18 version and document this as a breaking change.

@Tezra
Copy link
Author

Tezra commented Apr 3, 2024

I can. I don't think it will take that long to fix but I probably won't be able to work on it till this weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants