I've just upgraded from typescript 2.4 to 3.2 and now with the unknown type, the type system is stricter which trigger some errors that I didn't have before.
So I have an effect that retreive some possibly null data from the store and I want to make sure its not null by using a filter before dispatching my next action.
@Effect() saveSuccess$: Observable<Action> = this.actions$.pipe(
ofType(actions.SAVE_SUCCESS),
switchMapTo(this.store.pipe(select(selectors.getId))),
filter((id: number | null) => id !== null),
map((id: number) => new actions.GetData({ Id }))
);
The filter is now red saying:
Argument of type 'MonoTypeOperatorFunction<number | null>' is not assignable to parameter of type 'OperatorFunction<number | null, number>'.
Type 'Observable<number | null>' is not assignable to type 'Observable<number>'.
Type 'number | null' is not assignable to type 'number'.
Type 'null' is not assignable to type 'number'.ts(2345)
I can bypass the error by using any type but I feel like I shouldn't. If I change the map to accept number | null
it works but it makes no sens since its exactly the filter's job.
Try turning your filter function into a type guard by adding the return type id is number
. The type definition is set up so that if it receives a type guard, it will narrow the types:
this.actions$.pipe(
ofType(DCFActions.SAVE_SUCCESS),
switchMapTo(this.store.pipe(select(selectors.getId))),
filter((id: number | null): id is number => id !== null),
map((id: number) => new actions.GetData({ Id }))
);
If you wanted to make a more general filter function to filter out nulls from more things than just numbers, then you could write that like this:
const notNull = <T>(value: T | null): value is T => value !== null;
// ... to be used like:
filter(notNull);
You can read more about user-defined type guards here: https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With