我基于docs创建了一个reduce reducer,但是我使用的是typescript和redux文档,没有关于如何正确键入replace reducer的任何示例,我尝试了一下,但是我的尝试覆盖了{{ 1}}会忽略泛型而失去useStore
的类型。
组件:
getState()
redux配置:
interface State {
sim: number;
nao: string;
}
function Experimente() {
const store: InjectableStore = useStore<State>();
const dispatch = useDispatch();
store.getState(); // any
}
类型定义:
export const initStore = () => {
const store: StoreCreator & WithAsync = createStore(
createReducer(),
composeEnhancers(
applyMiddleware(thunk),
),
);
store.asyncReducers = {};
store.injectPageReducer = (pageReducer) => {
store.asyncReducers['page'] = pageReducer;
store.replaceReducer(createReducer(store.asyncReducers));
}
return store;
}
function createReducer(asyncReducers?) {
return combineReducers({
...staticReducers,
...asyncReducers
})
}
如何输入保持export interface WithAsync {
injectPageReducer?: (asyncReducer: Reducer) => void;
asyncReducers?: IGenericObject<any>;
replaceReducer?: typeof combineReducers;
}
export type InjectableStore = ReturnType<typeof useStore> & {
injectPageReducer?: WithAsync['injectPageReducer']
}
类型的replaceReducer
策略?
答案 0 :(得分:1)
问题是您的类型InjectableStore
没有收到有关您商店的任何信息。类型ReturnType<typeof useStore>
将不会应用您的特定状态类型,因为useStore
是通用的,但是您没有为其提供通用参数,因此它使用自己的默认值。 useState
的签名是:
export function useStore<S = RootStateOrAny, A extends Action = AnyAction>(): Store<S, A>;
所以ReturnType<typeof useStore>
变成Store<RootStateOrAny, AnyAction>
。
Store
,useStore
,Reducer
等都是泛型,它们依赖于两个值:S
是状态的形式,而{{1} },这是允许的操作的类型。 A
是可选的,默认情况下允许任何标准的A
。但是,如果未提供Action
,则这些类型对您的状态一无所知。
基本上,每次使用从“ redux”或“ react-redux”导入的类型时,都需要为其提供S
参数。您可以将S
之类的自定义类型设置为具有商店形状并将其传递的通用类型,也可以使它们始终将商店设置为接口InjectableStore
。第二种方法比较容易,所以让我们这样做。
您不能使用Store
,因为这是无效的语法,但这很好,因为我们在上面的函数签名中看到返回类型为ReturnType<typeof useStore<S, A>>
,在您的情况下为Store<S, A>
>
应用类型的需求更加深入,因为属性Store<State>
应该知道reducer不仅是{injectPageReducer: (asyncReducer: Reducer) => void;}
(暗含的),而且还特定于您的状态(或状态的一部分,在这种情况下)。
要变得棘手的部分是,当您调用Reducer<any>
函数(依次调用injectPageReducer
)时,您正在使用具有键{的对象来更改状态的形状{1}}和store.replaceReducer
到具有键sim
,nao
和sim
的对象。这很糟糕,我们不想这样做。 nao
函数的签名实际上告诉我们,替换变径器需要以与原始状态相同的状态page
进行操作:
replaceReducer
一个快速解决方案是将S
设为export interface Store<S = any, A extends Action = AnyAction> {
/** ... */
replaceReducer(nextReducer: Reducer<S, A>): void
/** ... */
}
的可选属性,但这会导致错误。最好将其设置为必需并设置默认值。
我实际上不喜欢将page
设置为State
的属性,而不是将临时变量传递给asyncReducers
来进行设置,但是我看到它直接来自{ {3}},所以我会顺其自然。
我摆脱了Store
并使其成为一个replaceReducer
界面,该界面具有WithAsync
的所有属性以及(也许)您的两个附加组件。由于附加组件是可选的,因此您需要在调用InjectableStore
之前先对其进行检查。
Store