N
N
nakonechnikistryi2022-03-29 14:34:52
typescript
nakonechnikistryi, 2022-03-29 14:34:52

How to assign an interface with required fields for a context without a default value?

There is a context in a separate context.ts file:

import React from 'react';
import SomeClass from '.....';

interface IContext {
  someClass: SomeClass;
}

// я должен назначить контексту интерфейс, чтобы видеть в других местах приложения его конкретные свойства
const Context= React.createContext<IContext>({});

export default Context;


And there will be an error here, because I didn’t throw an instance of SomeClass into the default value of the context. And in turn, I cannot create this instance of the class inside the file with the context, since this class requires a certain parameter in the constructor, to which there is no access. Everything is created somewhere else:

const someValue = 'someValue';

<Context.Provider value={{ someClass: new SomeClass(someValue ) }}>
  {children}
</Context.Provider>


How then to assign an interface to a context? To get rid of the error, I can only wrap the IContext in Partial to make the fields optional, but this is a so-so solution:

const Context= React.createContext<Partial<IContext >>({});

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexandroppolus, 2022-03-29
@nakonechnikistryi

In my opinion, this is the best option:

const Context= React.createContext(null as unknown as IContext);

...
const { someClass } = useContext(Context);

Yes, this is a typescript deception and the error will move to runtime, but in the case of the context, this cannot be avoided, because TS cannot control the presence of the provider. This option immediately detects an error in runtime during debugging, after which a one-time fix follows - a forgotten provider is added.
if the component that uses the value from the context can do without it, and for example, draw something meaningful, then you can do this:
const Context= React.createContext<IContext | null>(null);

then useContext will return IContext | null, that is, the value just needs to be checked for null and in this case, do something - for example, render some message. But if other hooks depend on the value of the context, then you need to stick a check everywhere and there will be an extra shitty code.
the worst option is to stick a meaningless stub in createContext that formally corresponds to the interface. This will also lead to an error at runtime (if the provider is forgotten), but the error will most likely be obscure, unlike the first option.
and of course, the context may contain something simple, for example, the current language, then setting the default value makes sense.

W
wonderingpeanut, 2022-03-29
@wonderingpeanut

interface MyLittleInterface {
  age: number;
  name: string;
}

const someVar: MyLittleInterface = {}; // ой-ой! 
const someOtherVar: MyLittleInterface = {} as MyLittleInterface; // Ура!

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question