更换减速机正确输入

时间:2020-10-02 18:02:47

标签: javascript reactjs typescript redux react-redux

我基于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策略?

1 个答案:

答案 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>

StoreuseStoreReducer等都是泛型,它们依赖于两个值: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到具有键simnaosim的对象。这很糟糕,我们不想这样做。 nao函数的签名实际上告诉我们,替换变径器需要以与原始状态相同的状态page进行操作:

replaceReducer

一个快速解决方案是将S设为export interface Store<S = any, A extends Action = AnyAction> { /** ... */ replaceReducer(nextReducer: Reducer<S, A>): void /** ... */ } 的可选属性,但这会导致错误。最好将其设置为必需并设置默认值。

我实际上不喜欢将page设置为State的属性,而不是将临时变量传递给asyncReducers来进行设置,但是我看到它直接来自{ {3}},所以我会顺其自然。

redux docs example

我摆脱了Store并使其成为一个replaceReducer界面,该界面具有WithAsync的所有属性以及(也许)您的两个附加组件。由于附加组件是可选的,因此您需要在调用InjectableStore之前先对其进行检查。

Store