There are 3 options I've seen in the wild.

Option 1

This option is a bit annoying because the type of StateContext value can be null | StateContextType. But in the code you provided, it will only be null on creation and not null inside the provider. Regardless, everywhere you use useContext you'll have to have a guard against null.

Copyimport React, { createContext, useState } from 'react';

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<null | StateContextType>(null);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};

Option 2

With this option, you cast StateContext value type to StateContextType. It means that the value of StateContext is assumed to be StateContextType. The only downside is that the value of StateContext is null for a very small amount of time at creation, before a value is provided in StateContext.Provider.

However, it's relatively safe since you're immediately passing a value in the provider.

Copyimport React, { createContext, useState } from 'react';

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<StateContextType>(
  null as unknown as StateContextType,
);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};

Option 3

Credit to Steve Kinney's course on Frontend Masters on React and TypeScript for this one.

Copyimport React, { useState } from 'react';

export function createContext<T>() {
  const context = React.createContext<T | undefined>(undefined);

  const useContext = () => {
    const value = React.useContext(context);
    if (value === undefined) {
      throw new Error(
        `useContext must be used inside a Provider with a value that's not undefined`,
      );
    }
    return value;
  };
  return [useContext, context.Provider] as const;
}

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const [useContext, Provider] = createContext<StateContextType>();

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return <Provider value={value}>{children}</Provider>;
};

const Component = () => {
  // usage inside component
  const context = useContext();
  return <div></div>;
};

export const App = () => {
  return (
    <ContextProvider>
      <Component />
    </ContextProvider>
  );
};
Answer from Spyros Argalias on Stack Overflow
🌐
DEV Community
dev.to › madv › usecontext-with-typescript-23ln
useContext() with Typescript - DEV Community
January 24, 2021 - The below article will give you an overview with an example of how to use the useContext() hook and also update the globally set context value in child components. Prerequisites: Basic familiarity with React and Typescript
Top answer
1 of 2
5

There are 3 options I've seen in the wild.

Option 1

This option is a bit annoying because the type of StateContext value can be null | StateContextType. But in the code you provided, it will only be null on creation and not null inside the provider. Regardless, everywhere you use useContext you'll have to have a guard against null.

Copyimport React, { createContext, useState } from 'react';

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<null | StateContextType>(null);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};

Option 2

With this option, you cast StateContext value type to StateContextType. It means that the value of StateContext is assumed to be StateContextType. The only downside is that the value of StateContext is null for a very small amount of time at creation, before a value is provided in StateContext.Provider.

However, it's relatively safe since you're immediately passing a value in the provider.

Copyimport React, { createContext, useState } from 'react';

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const StateContext = createContext<StateContextType>(
  null as unknown as StateContextType,
);

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return (
    <StateContext.Provider value={value}>{children}</StateContext.Provider>
  );
};

Option 3

Credit to Steve Kinney's course on Frontend Masters on React and TypeScript for this one.

Copyimport React, { useState } from 'react';

export function createContext<T>() {
  const context = React.createContext<T | undefined>(undefined);

  const useContext = () => {
    const value = React.useContext(context);
    if (value === undefined) {
      throw new Error(
        `useContext must be used inside a Provider with a value that's not undefined`,
      );
    }
    return value;
  };
  return [useContext, context.Provider] as const;
}

type StateContextType = {
  activeMenu: boolean;
  setActiveMenu: React.Dispatch<React.SetStateAction<boolean>>;
};

export const [useContext, Provider] = createContext<StateContextType>();

type ContextProviderProps = {
  children: React.ReactNode;
};

export const ContextProvider = ({ children }: ContextProviderProps) => {
  const [activeMenu, setActiveMenu] = useState(true);
  const value = {
    activeMenu,
    setActiveMenu,
  };

  return <Provider value={value}>{children}</Provider>;
};

const Component = () => {
  // usage inside component
  const context = useContext();
  return <div></div>;
};

export const App = () => {
  return (
    <ContextProvider>
      <Component />
    </ContextProvider>
  );
};
2 of 2
0

change this:

Copyimport React, {createContext, useContext, useState } from 'react';


const StateContext = createContext();

export const ContextProvider = ({ children }) => {
    const [activeMenu, setActiveMenu] = useState(true);

    return (
        <StateContext.Provider value={{activeMenu, setActiveMenu}}>
            {children}
        </StateContext.Provider>
    )
}

export const useStateContext = () => useContext(StateContext)

to this:

Copyimport React, {createContext, useContext, 
useState } from 'react';

interface Props {
children : ReactNode
}

const StateContext = createContext();

export const ContextProvider = ({ children }:Props) => {
    const [activeMenu, setActiveMenu] = useState(true);

    return (
        <StateContext.Provider value={{activeMenu, setActiveMenu}}>
            {children}
        </StateContext.Provider>
    )
}

export const useStateContext = () => useContext(StateContext)
People also ask

How does TypeScript help make useContext data more discoverable?
TypeScript allows developers to define the shape and types of data stored in context. By creating Type Aliases for objects like user and company, and using partial types in createContext, developers can ensure that IDEs provide auto-completion and type-checking for context values throughout the application.
🌐
fullstack.com
fullstack.com › labs › resources › blog › make-usecontext-data-more-discoverable-with-typescript
Make useContext Data More Discoverable with TypeScript
What is the useContext hook in React?
The useContext hook allows developers to manage global state in a React application without prop-drilling. It’s useful for passing data to deeply nested components that don’t share a common parent component, making state management simpler and more efficient.
🌐
fullstack.com
fullstack.com › labs › resources › blog › make-usecontext-data-more-discoverable-with-typescript
Make useContext Data More Discoverable with TypeScript
What is the problem with useContext data in plain JavaScript?
Without strong typing, the type and shape of data passed through context are not obvious. Developers may not know which properties exist on objects like user or company, and IDEs cannot provide helpful auto-completion or type-checking. This can make working with context less discoverable and error-prone.
🌐
fullstack.com
fullstack.com › labs › resources › blog › make-usecontext-data-more-discoverable-with-typescript
Make useContext Data More Discoverable with TypeScript
🌐
React TypeScript Cheatsheets
react-typescript-cheatsheet.netlify.app › context
Context | React TypeScript Cheatsheets
import { useContext } from "react"; const MyComponent = () => { const currentUser = useCurrentUser(); return <p>Username: {currentUser.username}.</p>; }; Another way to avoid having to check for null is to use type assertion to tell TypeScript you know the context is not null:
🌐
LogRocket
blog.logrocket.com › home › how to use react context with typescript
How to use React Context with TypeScript - LogRocket Blog
December 18, 2024 - It enables components to access React context values without passing props through intermediary components. When used with TypeScript, the useContext Hook adds an extra layer of type safety, ensuring correct types are used throughout the application.
🌐
CodeSandbox
codesandbox.io › s › typescript-react-usecontext-example-ufwux
typescript-react-usecontext-example - CodeSandbox
January 30, 2020 - typescript-react-usecontext-example by godon019 using react, react-dom, react-scripts
Published   Nov 26, 2019
Author   godon019
Find elsewhere
🌐
Medium
medium.com › @storydev123 › react-usecontext-and-typescript-c359065375e1
React useContext and Typescript. Managing global state in React can be a… | by Nick | Medium
June 14, 2023 - React useContext and Typescript Managing global state in React can be a complicated process, especially if you are using Redux, but the useContext is a great way to simplify this state management in …
🌐
Felix Gerschau
felixgerschau.com › how to use react context with typescript | felix gerschau
How to use React Context with TypeScript | Felix Gerschau
July 26, 2021 - As with useContext, TypeScript will infer the type from the default values or the interface we provided when creating the Context.
🌐
FullStack
fullstack.com › labs › resources › blog › make-usecontext-data-more-discoverable-with-typescript
Make useContext Data More Discoverable with TypeScript
By leveraging Typescript we can make data stored with the useContext hook to make the available properties more discoverable. The value of adding types with Typescript is not restricted to the useContext hook.
🌐
Medium
sterlingcobb.medium.com › using-react-usecontext-with-typescript-149f81bef096
Using React useContext with TypeScript | by Sterling Cobb | Medium
December 16, 2022 - Using React useContext with TypeScript React’s useContext hook allows you to consume context from a React context object in a function component. This can be a powerful tool for managing state and …
🌐
Reddit
reddit.com › r/reactjs › how to typescript usecontext?
r/reactjs on Reddit: How to typescript useContext?
July 11, 2024 -

Hi, i'm trying to correctly type (or maybe refactor) react's contextAPI in my app.

I use classic flow:

const myContext = createContext<MyContextObj | null>(null); // at first i create empty context.

function MyProvider...
// magic happens and i got my myContextObj object (in my case it contain `dispatch` from `useReducer()`, but it doesnt matter)

return
  <myContext.Provider value={myContextObj}> // At this point i provide actual context value.
...

The problem is, that context consumer assumes that context might me null (well, it was null at the moment of definition)

function Consumer...
const dispatchFn = useContext(myContext)

dispatchFn(...) // Typescript: Beware! dispatchFn can be null! Boo

What is a correct way of dealing with it?

// it works if i just:
const dispatchFn = useContext(myContext) as MyContextObj
// but maybe there is more appropriate way?
🌐
Reacttraining
reacttraining.com › blog › react-context-with-typescript
Working with React Context in TypeScript
February 10, 2021 - let { name, checked, handleChange } = React.useContext(RadioGroupContext) When we don't set an initial value, context will be undefined when we try to use it outside of the provider. So how could we address this? The obvious answer is to provide a default value. This will be a good time to write an interface for our context value type. ... And now we get rid of the TypeScript error!
🌐
DEV Community
dev.to › elisealcala › react-context-with-usereducer-and-typescript-4obm
useReducer TypeScript: React Context with useReducer and Typescript. - DEV Community
March 22, 2020 - /* Products.tsx */ import React, { useContext } from 'react'; import { AppContext } from './context'; import { Types } from './reducers'; const Products = () => { const { state, dispatch } = useContex(AppContext); return ( <div> <button onClick={() => { dispatch({ type: Types.Add, }) }}> click </button> {state.shoppingCart} </div> ) } export default Products; Everything it's strongly typed now. You can check the code here. https://medium.com/hackernoon/finally-the-typescript-redux-hooks-events-blog-you-were-looking-for-c4663d823b01 ·
🌐
Medium
medium.com › @ctrlaltmonique › how-to-use-usecontext-and-usereducer-with-typescript-in-react-735f6c5f27ba
How to use useContext and useReducer with TypeScript in React | by Monique McIntyre | Medium
June 7, 2024 - How to use useContext and useReducer with TypeScript in React Type-Safe State Management with React’s Built In Hooks Occasionally, resorting to an external state manager in our React projects might …
Top answer
1 of 2
5

First of all, you declare the context type like so:

export const Context = createContext<UserContextType | undefined>(undefined);

This means that the value of the context is either an object with all properties present of UserContextType or it is undefined.

Then here:

const [state, setState] = useState<IUser>();

You create state that has a type of IUser. But because you do not provide a default value, the default value is undefined. This is added to the state's type for you. So state is of type IUser | undefined.

Then we get here:

value={{state, setState}}

state is IUser | undefined, but the context type expects an IUser[] for that property. So neither IUser or undefined are valid types there.


First, you need to make sure that if you are passing in an object, then the object is correctly typed. That means that it has all required properties present. Else, pass in undefined. You can do this with a ternary expression:

value={state ? {state, setState} : undefined}

Now if state has a value, then the context value is created and passed it. Otherwise the context value is undefined.


But now you get this error:

    Types of property 'state' are incompatible.
      Type 'IUser' is missing the following properties from type 'IUser[]': length, pop, push, concat, and 26 more.(2322)

This is because you trying to assign a single user IUser to an array of users IUser[].

It looks like you mean for the content to only hold a single user, so you probably want to change the contexts type to:

export type UserContextType = {
    state: IUser;
    setState: (newSession: IUser) => void;
};

Which works, see playground

Or you need to pass in an array of users:

const UserProvider: React.FC<React.ReactNode> = ({ children }) => {
    const [state, setState] = useState<IUser[]>([]);

    return (
        <Context.Provider value={{state, setState}}>{children}</Context.Provider>
    )
};

Which also works, see playground


You could also change the context type to:

export type UserContextType = {
    state?: IUser;
    setState: (newSession: IUser) => void;
};

Which makes state optional, and then:

const UserProvider: React.FC<React.ReactNode> = ({ children }) => {
    const [state, setState] = useState<IUser>();

    return (
        <Context.Provider value={{state, setState}}>{children}</Context.Provider>
    )
};

Should work fine, see playground

2 of 2
-2

This is an example of a Context on Typescript

AuthContext.tsx:

import { createContext, ReactNode, useContext, useState } from "react";
import { AuthContextData } from "../models/AuthContextData.model";

const AuthContext = createContext<AuthContextData>({} as AuthContextData);

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  const [user, setUser] = useState<object | null>(null);
  const [loading, setLoading] = useState<boolean>(true);

  async function signIn(): Promise<void> {
   console.log('sign in')
  }

  async function signOut(): Promise<void> {
    console.log('sign out')
  }

  return (
    <AuthContext.Provider
      value={{ signed: !!user, user, signIn, signOut, loading }}
    >
      {children}
    </AuthContext.Provider>
  );
};

export function useAuth() {
  const context = useContext(AuthContext);
  return context;
}

AuthContextData.ts:

export interface AuthContextData {
  signed: boolean;
  user: object | null;
  signIn(): Promise<void>;
  signOut(): Promise<void>;
  loading: boolean;
}
🌐
DhiWise
dhiwise.com › post › a-beginner-guide-to-using-react-context-with-typescript
Creating and Using React Context with TypeScript
April 30, 2025 - To access the context value within a component, React provides the useContext hook . In TypeScript, you can use this hook with the context object you've created to ensure that the consumed context is of the correct type.
🌐
React
react.dev › reference › react › useContext
useContext – React
useContext returns the context value for the calling component. It is determined as the value passed to the closest SomeContext above the calling component in the tree. If there is no such provider, then the returned value will be the defaultValue ...
🌐
DEV Community
dev.to › shareef › context-api-with-typescript-and-next-js-2m25
Context API with TypeScript and Next.JS - DEV Community
April 4, 2021 - As we are using TypeScript we have to create types for our context · type authContextType = { user: boolean; login: () => void; logout: () => void; }; const authContextDefaultValues: authContextType = { user: null, login: () => {}, logout: () => {}, }; const AuthContext = createContext<authContextType>(authContextDefaultValues); export function useAuth() { return useContext(AuthContext); } type Props = { children: ReactNode; }; export function AuthProvider({ children }: Props) { const value = { } return ( <> <AuthContext.Provider value={value}> {children} </AuthContext.Provider> </> ); } We will wrap this AuthProvider function, where we want to use our context, and the value prop will have the values of authContextType.