15th March 2023

React Context with Typescript

Situation

I have a Next.js application that has a config.ts file. The config.ts file is only available on server-side and I would like to access some properties in the config file from the client side.

Solution

Create a React Context, import the Context into your _app.tsx file and use getInitialProps to fetch them server side and pass them as props to the context that wraps around your application that way they are now available to all pages in your app.

Easy right?

Uhmm... not quite

My issue comes in right at the beginning when creating the context. How do you initialize the context you create without having to manually hard-code default values and also set their types πŸ˜ͺ.

Here is solution 1;

import { ConfigTypes } from './config.ts'

export const ConfigContext = React.createContext<ConfigTypes>({} as ConfigInterface);

This solution means that the empty object we created has all those properties defined by ConfigTypes. The properties just don’t exist when the object is asserted to {}. This means that you can set a different value inside your context different from what is set in the config.ts which is not what we want. We only want it to get values from the config.ts

And this is how we fix that ⬇️

import { ConfigTypes } from './config.ts'

type ConfigContextValue = ConfigITypes | Record<string, never>
export const ConfigContext = React.createContext<ConfigContextValue>({});

Record<string, never> means that you can't pass an object that has string properties. It's the closest way to ensure an empty object.