I'm using Angular 11, TypeScript and NgRx as state management.
My app state contains a currentProject property which is retrieved from a backend. Hence, at initial startup the value is undefined.
export interface AppState {
currentProject?: Project; // <--- Note the ? to denote that at application startup there is no currentProject and hence the value can be undefined.
}
In the CurrentProjectComponent context in the app there always is a currentProject value in the state.
// Angular CurrentProjectComponent
....
public currentProject$!: Observable<Project>;
constructor(private store: Store<{ app: AppState >) {
this.currentProject$ = this.store.select((s) => s.currentProject);
}
...
But when I write code to select the code from the state, I end up in undesired type casting. I either have to
- type my
currentProject$field asProject | undefined, which leads to trouble when passing its value further to pipes and other components. I would end up in typing alsmost my whole domain model inProject | undefinedwhich kind of defeats the point. - add an
as Projectcast to the NgRx selector - filter out undefined currentProject values by writing:
this.store.select((s) => s.currentProject).pipe(filter(p => !!p));but this does not work either:
TS2322: Type 'Observable<Project | undefined>' is not assignable to type 'Observable < Project >'.
The best solution I could come up with is to filter undefined values and then cast:
constructor(private store: Store<{ app: AppState >) {
this.currentProject$ = this.store.select((s) => s.currentProject).pipe(filter(p => !!p)) as Observable<Project>;
}
But is this really needed in order to being able to use TypeScript? This solution does not feel like TypeScript is helping here.