Pablo Jurado

20 June, 2022

React context with TypeScript

How to add types to our React Context

If we follow the React docs to create a context provider we get the following example

export const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",
  },
};

export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});

This will work with TypeScript if we have void functions, but if we have more complex functions we might get a TypeScript error.

The trick to get proper Types on our context is to set the default value as an empty object and assign the type with the as keyword. Here is a full example:

type ThemeType = "dark" | "light";

interface ThemeProviderType {
  setTheme: React.Dispatch<React.SetStateAction<ThemeType>>;
  theme: ThemeType;
}

const ThemeContext = React.createContext<ThemeProviderType>(
  {} as ThemeProviderType
);

export const ThemeProvider = (props: { children: React.ReactNode }) => {
  const [theme, setTheme] = React.useState<ThemeType>("light");

  return (
    <>
      <ThemeContext.Provider value={{ theme, setTheme }}>
        {props.children}
      </ThemeContext.Provider>
    </>
  );
};

export function useTheme() {
  return React.useContext(ThemeContext);
}