Search code examples
reactjstypescriptreact-hooksreduceuse-reducer

Type 'boolean' is not assignable to type 'IArrowState'.ts(2322) in a Reducer function


I have the following code to define a React Reducer function:

import { useReducer, Reducer } from 'react';
interface IArrowState {
  ascending: [
    { time: boolean },
    { user: boolean }
  ]
}

type ArrowAction = {
  type: string;
}

const Events: FC<IEventComponent> & {getLayout: (params: any) => void;} = () => {
  const arrowInitialState: IArrowState = {
    ascending: [
      { time: true },
      { user: true }
    ]
  }

  const arrowReducer: Reducer<IArrowState, ArrowAction> = (state, action) => {
    switch (action.type) {
      case 'time':
        return state.ascending['time'] = !state.ascending['time'];
      case 'user':
        return state.ascending['user'] = !state.ascending['user'];
    }
  }
}

However I'm getting TS2322 Type A is not assignable to type B error on line const arrowReducer: Reducer<IArrowState, ArrowAction>:

enter image description here

Can someone explain what is going wrong here? Should I give a return type to Reducer<IArrowState, ArrowAction>?


Solution

  • You didn't update the state correctly, you must do the immutable update for the state in the reducer function. See immutable-update-patterns

    import type { Reducer } from 'react';
    
    interface IArrowState {
        ascending: [
            { time: boolean },
            { user: boolean }
        ]
    }
    
    type ArrowAction = {
        type: string;
    }
    
    const arrowInitialState: IArrowState = {
        ascending: [
            { time: true },
            { user: true }
        ]
    }
    
    const arrowReducer: Reducer<IArrowState, ArrowAction> = (state, action): IArrowState => {
        const [time, user] = state.ascending;
        switch (action.type) {
            case 'time':
                return {
                    ...state,
                    ascending: [{ time: !time.time }, user]
                }
            case 'user':
                return {
                    ...state,
                    ascending: [time, { user: !user.user }]
                }
            default:
                return state;
        }
    }
    
    const nextArrowState = arrowReducer(arrowInitialState, { type: 'time' });
    console.log('nextArrowState: ', nextArrowState);
    

    TS Playground(Click "Run" to check the logs in right panel)