Eva
Eva

Reputation: 467

Argument of type 'State' is not assignable to parameter of type 'never'

I have just started using typescript with React. I tried using it with React useReducer hook but I am stuck because of a weird error.

Here is my code:

    export interface ContractObj {
      company: string;
      negotiationRenewalDate: string;
      periodEnd: string;
      periodStart: string;
      scheduleForRenewal: boolean;
      contractId: string;
    }

    type State = {
      loading: boolean;
      error: boolean;
      contractsData: ContractObj[];
    };

    type Action =
      | { type: 'FETCH_SUCCESS'; payload: ContractObj[] }
      | { type: 'FETCH_ERROR'; payload: null };

    const initialState: State = {
      loading: true,
      error: false,
      contractsData: []
    };

    const reducer = (state: State, action: Action) => {
      switch (action.type) {
        case 'FETCH_SUCCESS':
          return {
            loading: false,
            error: false,
            contractsData: action.payload
          };
        case 'FETCH_ERROR':
          return {
            loading: false,
            error: true
          };
        default: {
          return state;
        }
      }
    };
    export const Contracts: React.FC<Props> = () => {
      const [state, dispatch] = useReducer(reducer, initialState);

It gives me an error when I hover over initialState i.e Argument of type 'State' is not assignable to parameter of type 'never'

Upvotes: 0

Views: 10016

Answers (1)

ford04
ford04

Reputation: 74620

Make sure to always return the same State type in the reducer function. If you hover over reducer, you see that it currently has following signature:

const reducer: (state: State, action: Action) => State | {loading: boolean; error: boolean;}

That is, because in case 'FETCH_ERROR',contractsData is left out, which is defined as required property in State. It can be fixed easily by adding an explicit return type to reducer function:

const reducer = (state: State, action: Action): State => { ... }

and you get the (in this case satisfying!) compile error complaining about the missing property. Finally you can either add an empty contractsData array in the 'FETCH_ERROR' case or define the property as optional in the State type.

Solution 1:

switch (action.type) {
    case 'FETCH_ERROR':
        return {
            loading: false,
            error: true,
            contractsData: []
        }
}

Solution 2:

type State = {
    loading: boolean;
    error: boolean;
    contractsData?: ContractObj[];
};

Playground

Upvotes: 6

Related Questions