Home > Software engineering >  How can I make my React context provider type safe
How can I make my React context provider type safe

Time:11-04

I have a React context provider. I wrote it in JS but I'm now rewriting it in TS. I'm having a hell of a time getting the types to work properly. The context is initialized with undefined. Later it is set with an action property, which can be any ActionCreator and an args property which can be any Action. I've tried a couple of different approaches but it's like whack a mole. This is what I currently have:

import { createContext, FC, PropsWithChildren, useState } from 'react'
import { Action, ActionCreator } from 'redux'
import { Dispatch, SetStateAction } from "react";

type ModalStateT = {
  action: ActionCreator<any> | undefined
  args: Action | undefined
}

type ModalContextT = {
  modalState: ModalStateT
  setModalState: Dispatch<SetStateAction<ModalStateT>>
  resetModalState: ({action, args}: ModalStateT) => void
}

export const ModalContext = createContext<ModalContextT | undefined>(undefined)

const ModalProvider: FC<PropsWithChildren> = ({ children }) => {

  const defaultState = {
    action: undefined,
    args: undefined,
  }
  const [modalState, setModalState] = useState(defaultState)

  const resetModalState = () => {
    setModalState(defaultState)
  }
  return (
    <ModalContext.Provider value={{ modalState, setModalState, resetModalState }}>
      { children }
    </ModalContext.Provider>
  )
}

export default ModalProvider

My IDE does shows errors here value={{ modalState, setModalState, resetModalState }}

This is the error I get:

TS2322: Type 'Dispatch<SetStateAction<{ action: undefined; args: undefined; }>>' is not assignable to type 'Dispatch<SetStateAction<ModalStateT>>'.
Type 'SetStateAction<ModalStateT>' is not assignable to type 'SetStateAction<{ action: undefined; args: undefined; }>'.
Type 'ModalStateT' is not assignable to type 'SetStateAction<{ action: undefined; args: undefined; }>'.
Type 'ModalStateT' is not assignable to type '{ action: undefined; args: undefined; }'. Types of property 'action' are incompatible.           
Type 'ActionCreator<any> | undefined' is not assignable to type 'undefined'.        
Type 'ActionCreator<any>' is not assignable to type 'undefined'.

How can I fix this? Thanks in advance!

CodePudding user response:

Annotate your defaultState with the ModalStateT type:

const defaultState: ModalStateT = {
  action: undefined,
  args: undefined,
}

otherwise TypeScript will infer a more restrictive type.

That is why it's giving you errors like:

Type 'ActionCreator<any>' is not assignable to type 'undefined'.

That is TypeScript telling you that it's inferred the type as undefined instead of the less restrictive ActionCreator<any> | undefined that you want it to be.

  • Related