The root of your problem is that you are trying to infer the type of an object after it's been created rather than understanding what type of object will be created. In my opinion, this is a backwards design.
It is better to avoid using typeof
when possible. There are things that you can make clear with a type
or interface
that typeof
cannot possibly infer on its own. Can the string
"myString" be any string
value, or is it a string literal? Can this null
property only ever be null
, or could it be null
or some other type? And what other type would that be? Hopefully you get the point.
dispatch
has a known type. It is a function which takes an action and returns void
. You do not need to use typeof dispatch
to get its type.
type Dispatch<A> = (value: A) => void;
The generic variable A
represents the acceptable action
arguments. What you use depends on how strictly-typed you want your app to be. You could set it to a union of your specific action types or to a general interface that all of your actions will fulfill. Redux exports general types Action
and AnyAction
but React doesn't, so you have to define it yourself.
interface MyAction {
type: string;
payload: any;
}
type MyDispatch = Dispatch<MyAction>
Likewise, you should already know the expected type/interface for your State
. If not, define it!
Here is a complete code example. The place to implement the types is on your initialState
and reducerAuth
. If those are typed properly, then StateProvider
does not need any extra typing as the useReducer
hook can infer the types of state
and dispatch
.
import React, { createContext, useReducer } from 'react';
interface MyState {
// some actual data here
}
// initialState must fulfill the `MyState` interface
const initialState: MyState = {};
// just an example, you can define this type however you want
interface MyAction {
type: string;
payload: any;
}
// reducer declaration depends on the types for `MyState` and `MyAction`
const reducerAuth = (state: MyState, action: MyAction): MyState => {
// actual reducer here
return state;
};
// these are the values in your context object
interface MyContext {
state: MyState;
dispatch: React.Dispatch<MyAction>
}
const ContextAuth = createContext<MyContext | null>(null);
const StateProvider = ({ children }: { children: JSX.Element }) => {
const { Provider } = ContextAuth;
const [state, dispatch] = useReducer(reducerAuth, initialState);
return (
<Provider value={{ state, dispatch }}>
{children}
</Provider>
);
};
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…