React + Redux-Observable + Typescript - Compilation, Argument Not Assignable Error












7















I am creating an app using React and Redux-Observable. I am new to this and I am trying to create an epic to execute the user login.



My epic is below:



export const loginUserEpic = (action$: ActionsObservable<Action>) =>
action$.pipe(
ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
switchMap((action: LoginAction) =>
ajax({
url,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { email: action.payload.username, password: action.payload.password },
}).pipe(
map((response: AjaxResponse) => loginSuccess(response.response.token)),
catchError((error: Error) => of(loginFailed(error))),
),
),
);


The problema is that I am getting a Typescript error on this line: ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION) saying this:



Argument of type '(source: Observable<LoginAction>) => Observable<LoginAction>' is not assignable to parameter of type 'OperatorFunction<Action<any>, LoginAction>'.
Types of parameters 'source' and 'source' are incompatible.
Type 'Observable<Action<any>>' is not assignable to type 'Observable<LoginAction>'.
Type 'Action<any>' is not assignable to type 'LoginAction'.
Property 'payload' is missing in type 'Action<any>'.


My actions are here:



export enum LoginActionTypes {
LOGIN_ACTION = 'login',
LOGIN_SUCCESS_ACTION = 'login-sucesss',
LOGIN_FAILED_ACTION = 'login-failed',
}

export interface LoginAction extends Action {
type: LoginActionTypes.LOGIN_ACTION;
payload: {
username: string;
password: string;
};
}

export function login(username: string, password: string): LoginAction {
return {
type: LoginActionTypes.LOGIN_ACTION,
payload: { username, password },
};
}

export interface LoginSuccessAction extends Action {
type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
payload: {
loginToken: string;
};
}

export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}

export interface LoginFailedAction extends Action {
type: LoginActionTypes.LOGIN_FAILED_ACTION;
payload: {
error: Error;
};
}

export function loginFailed(error: Error): LoginFailedAction {
return {
type: LoginActionTypes.LOGIN_FAILED_ACTION,
payload: { error },
};
}

export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;


How can I fix this without using any types on the Epic?










share|improve this question



























    7















    I am creating an app using React and Redux-Observable. I am new to this and I am trying to create an epic to execute the user login.



    My epic is below:



    export const loginUserEpic = (action$: ActionsObservable<Action>) =>
    action$.pipe(
    ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
    switchMap((action: LoginAction) =>
    ajax({
    url,
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: { email: action.payload.username, password: action.payload.password },
    }).pipe(
    map((response: AjaxResponse) => loginSuccess(response.response.token)),
    catchError((error: Error) => of(loginFailed(error))),
    ),
    ),
    );


    The problema is that I am getting a Typescript error on this line: ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION) saying this:



    Argument of type '(source: Observable<LoginAction>) => Observable<LoginAction>' is not assignable to parameter of type 'OperatorFunction<Action<any>, LoginAction>'.
    Types of parameters 'source' and 'source' are incompatible.
    Type 'Observable<Action<any>>' is not assignable to type 'Observable<LoginAction>'.
    Type 'Action<any>' is not assignable to type 'LoginAction'.
    Property 'payload' is missing in type 'Action<any>'.


    My actions are here:



    export enum LoginActionTypes {
    LOGIN_ACTION = 'login',
    LOGIN_SUCCESS_ACTION = 'login-sucesss',
    LOGIN_FAILED_ACTION = 'login-failed',
    }

    export interface LoginAction extends Action {
    type: LoginActionTypes.LOGIN_ACTION;
    payload: {
    username: string;
    password: string;
    };
    }

    export function login(username: string, password: string): LoginAction {
    return {
    type: LoginActionTypes.LOGIN_ACTION,
    payload: { username, password },
    };
    }

    export interface LoginSuccessAction extends Action {
    type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
    payload: {
    loginToken: string;
    };
    }

    export function loginSuccess(loginToken: string): LoginSuccessAction {
    return {
    type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
    payload: { loginToken },
    };
    }

    export interface LoginFailedAction extends Action {
    type: LoginActionTypes.LOGIN_FAILED_ACTION;
    payload: {
    error: Error;
    };
    }

    export function loginFailed(error: Error): LoginFailedAction {
    return {
    type: LoginActionTypes.LOGIN_FAILED_ACTION,
    payload: { error },
    };
    }

    export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;


    How can I fix this without using any types on the Epic?










    share|improve this question

























      7












      7








      7


      1






      I am creating an app using React and Redux-Observable. I am new to this and I am trying to create an epic to execute the user login.



      My epic is below:



      export const loginUserEpic = (action$: ActionsObservable<Action>) =>
      action$.pipe(
      ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
      switchMap((action: LoginAction) =>
      ajax({
      url,
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: { email: action.payload.username, password: action.payload.password },
      }).pipe(
      map((response: AjaxResponse) => loginSuccess(response.response.token)),
      catchError((error: Error) => of(loginFailed(error))),
      ),
      ),
      );


      The problema is that I am getting a Typescript error on this line: ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION) saying this:



      Argument of type '(source: Observable<LoginAction>) => Observable<LoginAction>' is not assignable to parameter of type 'OperatorFunction<Action<any>, LoginAction>'.
      Types of parameters 'source' and 'source' are incompatible.
      Type 'Observable<Action<any>>' is not assignable to type 'Observable<LoginAction>'.
      Type 'Action<any>' is not assignable to type 'LoginAction'.
      Property 'payload' is missing in type 'Action<any>'.


      My actions are here:



      export enum LoginActionTypes {
      LOGIN_ACTION = 'login',
      LOGIN_SUCCESS_ACTION = 'login-sucesss',
      LOGIN_FAILED_ACTION = 'login-failed',
      }

      export interface LoginAction extends Action {
      type: LoginActionTypes.LOGIN_ACTION;
      payload: {
      username: string;
      password: string;
      };
      }

      export function login(username: string, password: string): LoginAction {
      return {
      type: LoginActionTypes.LOGIN_ACTION,
      payload: { username, password },
      };
      }

      export interface LoginSuccessAction extends Action {
      type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
      payload: {
      loginToken: string;
      };
      }

      export function loginSuccess(loginToken: string): LoginSuccessAction {
      return {
      type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
      payload: { loginToken },
      };
      }

      export interface LoginFailedAction extends Action {
      type: LoginActionTypes.LOGIN_FAILED_ACTION;
      payload: {
      error: Error;
      };
      }

      export function loginFailed(error: Error): LoginFailedAction {
      return {
      type: LoginActionTypes.LOGIN_FAILED_ACTION,
      payload: { error },
      };
      }

      export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;


      How can I fix this without using any types on the Epic?










      share|improve this question














      I am creating an app using React and Redux-Observable. I am new to this and I am trying to create an epic to execute the user login.



      My epic is below:



      export const loginUserEpic = (action$: ActionsObservable<Action>) =>
      action$.pipe(
      ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
      switchMap((action: LoginAction) =>
      ajax({
      url,
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: { email: action.payload.username, password: action.payload.password },
      }).pipe(
      map((response: AjaxResponse) => loginSuccess(response.response.token)),
      catchError((error: Error) => of(loginFailed(error))),
      ),
      ),
      );


      The problema is that I am getting a Typescript error on this line: ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION) saying this:



      Argument of type '(source: Observable<LoginAction>) => Observable<LoginAction>' is not assignable to parameter of type 'OperatorFunction<Action<any>, LoginAction>'.
      Types of parameters 'source' and 'source' are incompatible.
      Type 'Observable<Action<any>>' is not assignable to type 'Observable<LoginAction>'.
      Type 'Action<any>' is not assignable to type 'LoginAction'.
      Property 'payload' is missing in type 'Action<any>'.


      My actions are here:



      export enum LoginActionTypes {
      LOGIN_ACTION = 'login',
      LOGIN_SUCCESS_ACTION = 'login-sucesss',
      LOGIN_FAILED_ACTION = 'login-failed',
      }

      export interface LoginAction extends Action {
      type: LoginActionTypes.LOGIN_ACTION;
      payload: {
      username: string;
      password: string;
      };
      }

      export function login(username: string, password: string): LoginAction {
      return {
      type: LoginActionTypes.LOGIN_ACTION,
      payload: { username, password },
      };
      }

      export interface LoginSuccessAction extends Action {
      type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
      payload: {
      loginToken: string;
      };
      }

      export function loginSuccess(loginToken: string): LoginSuccessAction {
      return {
      type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
      payload: { loginToken },
      };
      }

      export interface LoginFailedAction extends Action {
      type: LoginActionTypes.LOGIN_FAILED_ACTION;
      payload: {
      error: Error;
      };
      }

      export function loginFailed(error: Error): LoginFailedAction {
      return {
      type: LoginActionTypes.LOGIN_FAILED_ACTION,
      payload: { error },
      };
      }

      export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;


      How can I fix this without using any types on the Epic?







      reactjs typescript rxjs redux-observable






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 15:28









      FelipeFelipe

      1,21911731




      1,21911731
























          3 Answers
          3






          active

          oldest

          votes


















          3





          +25









          The ofType operator offered by redux-observable is not the best way to discriminate union types. A much better way is to use the isOfType function provided by typesafe-actions.



          import { filter } from 'rxjs/operators';
          import { isOfType } from 'typesafe-actions';


          First, let's tell TypeScript about the possible actions used in your application. Your action stream should not be defined as ActionsObservable<Action>, but as a stream of your actions: ActionsObservable<LoginActions>.



          export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>


          Now we can use the isOfType predicate together with the filter operator. Replace this:



          ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)


          with this:



          filter(isOfType(LoginActionTypes.LOGIN_ACTION))


          The action passed down the stream will be correctly recognized as LoginAction.






          share|improve this answer































            0














            You can checkout https://github.com/piotrwitek/react-redux-typescript-guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.



            I would suggest using typesafe-actions library to achieve the types.



            Some pseudo codes:



            Actions



            Instead of this



            export interface LoginSuccessAction extends Action {
            type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
            payload: {
            loginToken: string;
            };
            }

            export function loginSuccess(loginToken: string): LoginSuccessAction {
            return {
            type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
            payload: { loginToken },
            };
            }



            use typesafe-actions, without interface



            actions/login/LoginActions.ts



            import {action} from "typesafe-actions"

            export function loginSuccess(loginToken: string) {
            return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
            }


            actions/login/LoginActionsModel.ts



            import * LoginActions from "./LoginActions";
            import { ActionCreator } from "typesafe-actions";

            export type LoginActionCreator = ActionCreator<typeof LoginActions>


            Then export out All Actions.



            actions/index.ts



            import { LoginActionCreator } from "./login/LoginActionModel";

            export default type AllActions = LoginActionCreator


            Epics



            import { Epic } from "redux-observable";
            import { isOfType } from "typesafe-actions";
            import { filter } from "rxjs/operators";


            export const loginUserEpic: Epic<AllActions> = (action$) =>
            action$.pipe(
            filter(isOfType((LoginActionTypes.LOGIN_ACTION))),
            switchMap((action: LoginAction) =>
            ajax({
            url,
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: { email: action.payload.username, password: action.payload.password },
            }).pipe(
            map((response: AjaxResponse) => loginSuccess(response.response.token)),
            catchError((error: Error) => of(loginFailed(error))),
            ),
            ),
            );


            Where the Epics is from redux-observable library, AllActions are the actions that is input and output of the epics.



            The types is as follows:



            Epic<InputActions, OutputActions, Store>
            Epic<Actions(Input&Output)>


            In case you want to use store from redux, you need a RootState (from root reducer)



            export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$) 
            => action$.pipe(
            filter(isOfType(SOMETYPE)),
            mergeMap(action => {
            const a = store$.value.a;
            return someActions(a, action.payload.b);
            })





            share|improve this answer

































              0














              Typescript gives an error because you have set to ActionsObservable action generic a redux Action that is an interface with form of { type: string }. So Typescript thinks that all the actions coming will have only type, but you are setting to ofType filtering operator another type of Action, even if it extends redux Action interface Typescript will require bivarianceHack to allow you pass anything that implements that interface. One of the simplest workarounds is to change ActionsObservable<Action> to ActionsObservable<AnyAction>, with AnyAction which is imported from redux.






              share|improve this answer























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415353%2freact-redux-observable-typescript-compilation-argument-not-assignable-err%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                3





                +25









                The ofType operator offered by redux-observable is not the best way to discriminate union types. A much better way is to use the isOfType function provided by typesafe-actions.



                import { filter } from 'rxjs/operators';
                import { isOfType } from 'typesafe-actions';


                First, let's tell TypeScript about the possible actions used in your application. Your action stream should not be defined as ActionsObservable<Action>, but as a stream of your actions: ActionsObservable<LoginActions>.



                export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>


                Now we can use the isOfType predicate together with the filter operator. Replace this:



                ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)


                with this:



                filter(isOfType(LoginActionTypes.LOGIN_ACTION))


                The action passed down the stream will be correctly recognized as LoginAction.






                share|improve this answer




























                  3





                  +25









                  The ofType operator offered by redux-observable is not the best way to discriminate union types. A much better way is to use the isOfType function provided by typesafe-actions.



                  import { filter } from 'rxjs/operators';
                  import { isOfType } from 'typesafe-actions';


                  First, let's tell TypeScript about the possible actions used in your application. Your action stream should not be defined as ActionsObservable<Action>, but as a stream of your actions: ActionsObservable<LoginActions>.



                  export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>


                  Now we can use the isOfType predicate together with the filter operator. Replace this:



                  ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)


                  with this:



                  filter(isOfType(LoginActionTypes.LOGIN_ACTION))


                  The action passed down the stream will be correctly recognized as LoginAction.






                  share|improve this answer


























                    3





                    +25







                    3





                    +25



                    3




                    +25





                    The ofType operator offered by redux-observable is not the best way to discriminate union types. A much better way is to use the isOfType function provided by typesafe-actions.



                    import { filter } from 'rxjs/operators';
                    import { isOfType } from 'typesafe-actions';


                    First, let's tell TypeScript about the possible actions used in your application. Your action stream should not be defined as ActionsObservable<Action>, but as a stream of your actions: ActionsObservable<LoginActions>.



                    export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>


                    Now we can use the isOfType predicate together with the filter operator. Replace this:



                    ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)


                    with this:



                    filter(isOfType(LoginActionTypes.LOGIN_ACTION))


                    The action passed down the stream will be correctly recognized as LoginAction.






                    share|improve this answer













                    The ofType operator offered by redux-observable is not the best way to discriminate union types. A much better way is to use the isOfType function provided by typesafe-actions.



                    import { filter } from 'rxjs/operators';
                    import { isOfType } from 'typesafe-actions';


                    First, let's tell TypeScript about the possible actions used in your application. Your action stream should not be defined as ActionsObservable<Action>, but as a stream of your actions: ActionsObservable<LoginActions>.



                    export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>


                    Now we can use the isOfType predicate together with the filter operator. Replace this:



                    ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)


                    with this:



                    filter(isOfType(LoginActionTypes.LOGIN_ACTION))


                    The action passed down the stream will be correctly recognized as LoginAction.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jan 20 at 18:02









                    Karol MajewskiKarol Majewski

                    3,156213




                    3,156213

























                        0














                        You can checkout https://github.com/piotrwitek/react-redux-typescript-guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.



                        I would suggest using typesafe-actions library to achieve the types.



                        Some pseudo codes:



                        Actions



                        Instead of this



                        export interface LoginSuccessAction extends Action {
                        type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
                        payload: {
                        loginToken: string;
                        };
                        }

                        export function loginSuccess(loginToken: string): LoginSuccessAction {
                        return {
                        type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
                        payload: { loginToken },
                        };
                        }



                        use typesafe-actions, without interface



                        actions/login/LoginActions.ts



                        import {action} from "typesafe-actions"

                        export function loginSuccess(loginToken: string) {
                        return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
                        }


                        actions/login/LoginActionsModel.ts



                        import * LoginActions from "./LoginActions";
                        import { ActionCreator } from "typesafe-actions";

                        export type LoginActionCreator = ActionCreator<typeof LoginActions>


                        Then export out All Actions.



                        actions/index.ts



                        import { LoginActionCreator } from "./login/LoginActionModel";

                        export default type AllActions = LoginActionCreator


                        Epics



                        import { Epic } from "redux-observable";
                        import { isOfType } from "typesafe-actions";
                        import { filter } from "rxjs/operators";


                        export const loginUserEpic: Epic<AllActions> = (action$) =>
                        action$.pipe(
                        filter(isOfType((LoginActionTypes.LOGIN_ACTION))),
                        switchMap((action: LoginAction) =>
                        ajax({
                        url,
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: { email: action.payload.username, password: action.payload.password },
                        }).pipe(
                        map((response: AjaxResponse) => loginSuccess(response.response.token)),
                        catchError((error: Error) => of(loginFailed(error))),
                        ),
                        ),
                        );


                        Where the Epics is from redux-observable library, AllActions are the actions that is input and output of the epics.



                        The types is as follows:



                        Epic<InputActions, OutputActions, Store>
                        Epic<Actions(Input&Output)>


                        In case you want to use store from redux, you need a RootState (from root reducer)



                        export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$) 
                        => action$.pipe(
                        filter(isOfType(SOMETYPE)),
                        mergeMap(action => {
                        const a = store$.value.a;
                        return someActions(a, action.payload.b);
                        })





                        share|improve this answer






























                          0














                          You can checkout https://github.com/piotrwitek/react-redux-typescript-guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.



                          I would suggest using typesafe-actions library to achieve the types.



                          Some pseudo codes:



                          Actions



                          Instead of this



                          export interface LoginSuccessAction extends Action {
                          type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
                          payload: {
                          loginToken: string;
                          };
                          }

                          export function loginSuccess(loginToken: string): LoginSuccessAction {
                          return {
                          type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
                          payload: { loginToken },
                          };
                          }



                          use typesafe-actions, without interface



                          actions/login/LoginActions.ts



                          import {action} from "typesafe-actions"

                          export function loginSuccess(loginToken: string) {
                          return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
                          }


                          actions/login/LoginActionsModel.ts



                          import * LoginActions from "./LoginActions";
                          import { ActionCreator } from "typesafe-actions";

                          export type LoginActionCreator = ActionCreator<typeof LoginActions>


                          Then export out All Actions.



                          actions/index.ts



                          import { LoginActionCreator } from "./login/LoginActionModel";

                          export default type AllActions = LoginActionCreator


                          Epics



                          import { Epic } from "redux-observable";
                          import { isOfType } from "typesafe-actions";
                          import { filter } from "rxjs/operators";


                          export const loginUserEpic: Epic<AllActions> = (action$) =>
                          action$.pipe(
                          filter(isOfType((LoginActionTypes.LOGIN_ACTION))),
                          switchMap((action: LoginAction) =>
                          ajax({
                          url,
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: { email: action.payload.username, password: action.payload.password },
                          }).pipe(
                          map((response: AjaxResponse) => loginSuccess(response.response.token)),
                          catchError((error: Error) => of(loginFailed(error))),
                          ),
                          ),
                          );


                          Where the Epics is from redux-observable library, AllActions are the actions that is input and output of the epics.



                          The types is as follows:



                          Epic<InputActions, OutputActions, Store>
                          Epic<Actions(Input&Output)>


                          In case you want to use store from redux, you need a RootState (from root reducer)



                          export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$) 
                          => action$.pipe(
                          filter(isOfType(SOMETYPE)),
                          mergeMap(action => {
                          const a = store$.value.a;
                          return someActions(a, action.payload.b);
                          })





                          share|improve this answer




























                            0












                            0








                            0







                            You can checkout https://github.com/piotrwitek/react-redux-typescript-guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.



                            I would suggest using typesafe-actions library to achieve the types.



                            Some pseudo codes:



                            Actions



                            Instead of this



                            export interface LoginSuccessAction extends Action {
                            type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
                            payload: {
                            loginToken: string;
                            };
                            }

                            export function loginSuccess(loginToken: string): LoginSuccessAction {
                            return {
                            type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
                            payload: { loginToken },
                            };
                            }



                            use typesafe-actions, without interface



                            actions/login/LoginActions.ts



                            import {action} from "typesafe-actions"

                            export function loginSuccess(loginToken: string) {
                            return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
                            }


                            actions/login/LoginActionsModel.ts



                            import * LoginActions from "./LoginActions";
                            import { ActionCreator } from "typesafe-actions";

                            export type LoginActionCreator = ActionCreator<typeof LoginActions>


                            Then export out All Actions.



                            actions/index.ts



                            import { LoginActionCreator } from "./login/LoginActionModel";

                            export default type AllActions = LoginActionCreator


                            Epics



                            import { Epic } from "redux-observable";
                            import { isOfType } from "typesafe-actions";
                            import { filter } from "rxjs/operators";


                            export const loginUserEpic: Epic<AllActions> = (action$) =>
                            action$.pipe(
                            filter(isOfType((LoginActionTypes.LOGIN_ACTION))),
                            switchMap((action: LoginAction) =>
                            ajax({
                            url,
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: { email: action.payload.username, password: action.payload.password },
                            }).pipe(
                            map((response: AjaxResponse) => loginSuccess(response.response.token)),
                            catchError((error: Error) => of(loginFailed(error))),
                            ),
                            ),
                            );


                            Where the Epics is from redux-observable library, AllActions are the actions that is input and output of the epics.



                            The types is as follows:



                            Epic<InputActions, OutputActions, Store>
                            Epic<Actions(Input&Output)>


                            In case you want to use store from redux, you need a RootState (from root reducer)



                            export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$) 
                            => action$.pipe(
                            filter(isOfType(SOMETYPE)),
                            mergeMap(action => {
                            const a = store$.value.a;
                            return someActions(a, action.payload.b);
                            })





                            share|improve this answer















                            You can checkout https://github.com/piotrwitek/react-redux-typescript-guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.



                            I would suggest using typesafe-actions library to achieve the types.



                            Some pseudo codes:



                            Actions



                            Instead of this



                            export interface LoginSuccessAction extends Action {
                            type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
                            payload: {
                            loginToken: string;
                            };
                            }

                            export function loginSuccess(loginToken: string): LoginSuccessAction {
                            return {
                            type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
                            payload: { loginToken },
                            };
                            }



                            use typesafe-actions, without interface



                            actions/login/LoginActions.ts



                            import {action} from "typesafe-actions"

                            export function loginSuccess(loginToken: string) {
                            return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
                            }


                            actions/login/LoginActionsModel.ts



                            import * LoginActions from "./LoginActions";
                            import { ActionCreator } from "typesafe-actions";

                            export type LoginActionCreator = ActionCreator<typeof LoginActions>


                            Then export out All Actions.



                            actions/index.ts



                            import { LoginActionCreator } from "./login/LoginActionModel";

                            export default type AllActions = LoginActionCreator


                            Epics



                            import { Epic } from "redux-observable";
                            import { isOfType } from "typesafe-actions";
                            import { filter } from "rxjs/operators";


                            export const loginUserEpic: Epic<AllActions> = (action$) =>
                            action$.pipe(
                            filter(isOfType((LoginActionTypes.LOGIN_ACTION))),
                            switchMap((action: LoginAction) =>
                            ajax({
                            url,
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: { email: action.payload.username, password: action.payload.password },
                            }).pipe(
                            map((response: AjaxResponse) => loginSuccess(response.response.token)),
                            catchError((error: Error) => of(loginFailed(error))),
                            ),
                            ),
                            );


                            Where the Epics is from redux-observable library, AllActions are the actions that is input and output of the epics.



                            The types is as follows:



                            Epic<InputActions, OutputActions, Store>
                            Epic<Actions(Input&Output)>


                            In case you want to use store from redux, you need a RootState (from root reducer)



                            export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$) 
                            => action$.pipe(
                            filter(isOfType(SOMETYPE)),
                            mergeMap(action => {
                            const a = store$.value.a;
                            return someActions(a, action.payload.b);
                            })






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Jan 22 at 10:37

























                            answered Jan 22 at 10:32









                            johnson laijohnson lai

                            194110




                            194110























                                0














                                Typescript gives an error because you have set to ActionsObservable action generic a redux Action that is an interface with form of { type: string }. So Typescript thinks that all the actions coming will have only type, but you are setting to ofType filtering operator another type of Action, even if it extends redux Action interface Typescript will require bivarianceHack to allow you pass anything that implements that interface. One of the simplest workarounds is to change ActionsObservable<Action> to ActionsObservable<AnyAction>, with AnyAction which is imported from redux.






                                share|improve this answer




























                                  0














                                  Typescript gives an error because you have set to ActionsObservable action generic a redux Action that is an interface with form of { type: string }. So Typescript thinks that all the actions coming will have only type, but you are setting to ofType filtering operator another type of Action, even if it extends redux Action interface Typescript will require bivarianceHack to allow you pass anything that implements that interface. One of the simplest workarounds is to change ActionsObservable<Action> to ActionsObservable<AnyAction>, with AnyAction which is imported from redux.






                                  share|improve this answer


























                                    0












                                    0








                                    0







                                    Typescript gives an error because you have set to ActionsObservable action generic a redux Action that is an interface with form of { type: string }. So Typescript thinks that all the actions coming will have only type, but you are setting to ofType filtering operator another type of Action, even if it extends redux Action interface Typescript will require bivarianceHack to allow you pass anything that implements that interface. One of the simplest workarounds is to change ActionsObservable<Action> to ActionsObservable<AnyAction>, with AnyAction which is imported from redux.






                                    share|improve this answer













                                    Typescript gives an error because you have set to ActionsObservable action generic a redux Action that is an interface with form of { type: string }. So Typescript thinks that all the actions coming will have only type, but you are setting to ofType filtering operator another type of Action, even if it extends redux Action interface Typescript will require bivarianceHack to allow you pass anything that implements that interface. One of the simplest workarounds is to change ActionsObservable<Action> to ActionsObservable<AnyAction>, with AnyAction which is imported from redux.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Jan 25 at 6:49









                                    iamawebgeekiamawebgeek

                                    1,325728




                                    1,325728






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415353%2freact-redux-observable-typescript-compilation-argument-not-assignable-err%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        android studio warns about leanback feature tag usage required on manifest while using Unity exported app?

                                        SQL update select statement

                                        'app-layout' is not a known element: how to share Component with different Modules