0

I am relatively new to Typescript and am currently building a React app which includes Redux and am using Typescript.

Typescript is giving me the following error in my reducer;

ERROR in /Users/<REDACTED>/web/src/redux/reducers/steppedViews.ts
./src/redux/reducers/steppedViews.ts
[tsl] ERROR in /Users/<REDACTED>/web/src/redux/reducers/steppedViews.ts(13,53)
      TS2339: Property 'activeView' does not exist on type '{ activeView: number; } | { totalViews: number; }'.
  Property 'activeView' does not exist on type '{ totalViews: number; }'.

ERROR in /Users/<REDACTED>/web/src/redux/reducers/steppedViews.ts
./src/redux/reducers/steppedViews.ts
[tsl] ERROR in /Users/<REDACTED>/web/src/redux/reducers/steppedViews.ts(15,53)
      TS2339: Property 'totalViews' does not exist on type '{ activeView: number; } | { totalViews: number; }'.
  Property 'totalViews' does not exist on type '{ activeView: number; }'.

My action typ definition is as follows

export interface SetActiveView {
  type: typeof types.steppedViews.SET_ACTIVE_VIEW;
  payload: {
    activeView: number;
  };
}

export interface SetTotalViews {
  type: typeof types.steppedViews.SET_TOTAL_VIEWS;
  payload: { totalViews: number };
}

export type ReduxActionsSteppedViews = SetActiveView | SetTotalViews;

And my reducer is

import types from '../types';
import { ReduxActionsSteppedViews } from '../actions/steppedViews';

export interface ReduxStateSteppedView {
  activeView: number;
  totalViews: number;
}
const initialState: ReduxStateSteppedView = { activeView: 0, totalViews: 0 };

const reducer = (state = initialState, action: ReduxActionsSteppedViews): ReduxStateSteppedView => {
  switch (action.type) {
    case types.steppedViews.SET_ACTIVE_VIEW:
      return { ...state, activeView: action.payload.activeView };
    case types.steppedViews.SET_TOTAL_VIEWS:
      return { ...state, totalViews: action.payload.totalViews };
    default:
      return state;
  }
};

export default reducer;

I am confused as to why this is happening because from my understanding, the type defined is '{activeView: number;} | {totalViews: number;}' so it should be able to see either *.activeView or *.totalViews.

Any guidance on this error would be greatly appreciated. Thanks!

1 Answer 1

1

Declared type is {activeView: number;} | {totalViews: number;}, so neither activeView or totalViews are required property in ReduxActionsSteppedViews.payload

Typescript does not know if you have done type checked (in your case), so you need to tell her:

const reducer = (state = initialState, action: ReduxActionsSteppedViews): ReduxStateSteppedView => {
  switch (action.type) {
    case types.steppedViews.SET_ACTIVE_VIEW:
      return { ...state, activeView: (<SetActiveView> action).payload.activeView };
    case types.steppedViews.SET_TOTAL_VIEWS:
      return { ...state, totalViews:(< SetTotalViews> action).payload.totalViews };
    default:
      return state;
  }
};
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your answer. That has of course done the trick but doesn't feel very neat. Is there a way I can change my code to make this a little neater? I followed the react-redux guide to using it in typescript to arrive at the merged type definition for actions. Or is this solution acceptable?
If you don't like to create only one interface that merges two interfaces with ? and ` |` operators, I think this is the only approach. :)
See also: stackoverflow.com/questions/62956678/… , this post might help you understand conditional typing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.