Cannot invoke an object which is possibly 'undefined'. TS2722
Использую связку useContext & useReducer с typescript. При попытке использовать useContext в child-компоненте идет ошибка Cannot invoke an object which is possibly 'undefined'. TS2722. Я не указывал, что тип может быть undefined.
Хроника действий:
Создал context в родительском компоненте с типизацией:
export const initialState: State = {
newTask: '',
tasks: []
}
export const ContextApp = React.createContext<Partial<ContextState>>({});
export const Main: React.FC = () => {
const [state, changeState] = useReducer<React.Reducer<State, Action>>(todoReducer, initialState);
const ContextState: ContextState = {
state,
changeState
};
return (
<ContextApp.Provider value={ContextState}>
{/* <div className={styles.mainWrapper}> */}
<Panel />
<ListItems />
{/* </div> */}
</ContextApp.Provider>
)
}
Тот самый тип ContextState:
export type ContextState = {
state: State;
changeState: Dispatch<Action>
}
Место ошибки(чайлд компонент). При попытке использовал changeState выходит выше описанная ошибка:
const { state, changeState } = useContext(ContextApp);
const removeTask = (taskForRemoving: Task) => {
//Подсвечивается красным (ошибка) ---->
changeState({ type: ActionType.Remove, payload: taskForRemoving })
}
Что я пытался сделать?
Нагуглил пару запросов на stackoverflow. Все, что я нашел, но не подходит под мой случай:
- https://stackoverflow.com/questions/56913963/cannot-invoke-an-object-which-is-possibly-undefined-ts2722
- https://stackoverflow.com/questions/60312057/how-to-remove-ts2722-cannot-invoke-an-object-which-is-possibly-undefined-err?rq=1
Ответы (2 шт):
Так как в определении типа контекста используется Partial, любое из полей может отсутствовать.
Таким образом, может быть, что в какой-то момент changeState будет undefined, что приведет к ошибке при попытке выполнить его как функцию.
Для решения нужно либо убрать Partial из определения типа
React.createContext<ContextState>();
Либо при вызове использовать optional chaining operator
changeState?.({ type: ActionType.Remove, payload: taskForRemoving })