Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript with RxJS filter typing problem

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.

like image 429
ukn Avatar asked Jul 25 '19 16:07

ukn


1 Answers

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

like image 191
Nicholas Tower Avatar answered Nov 13 '22 13:11

Nicholas Tower