Reputation: 467
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
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[];
};
Upvotes: 6