如何在 TS 中正确输入 `Redux` 增强器?

How to properly type `Redux` enhancer in TS?

我想将 meaingOfFile 属性 添加到我的 redux 状态:

...
type CustomProps = 
{
    meaingOfFile: number;
}
const ResourceEnhancer: StoreEnhancer<{}, CustomProps> = (createStore) => (reducer, initialState) =>
{
    console.log("custom enhancer");
    const store = createStore(reducer, initialState);
    
    function getNewState()
    {
        return {
            ...store.getState(),
            meaingOfFile: 32,
        }
    }
    
    return { ...store, getState: getNewState};
}

const Store = configureStore({
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(LocalStorageMiddleware),
    enhancers: (defaultEnhancers) => [ResourceEnhancer, ...defaultEnhancers],
    reducer:{
        books: BooksSlice.reducer,
        shelfs: ShelfsSlice.reducer,
    }
});

但是TS抛出错误:

TS2322: Type '<S = any, A extends Action<any> = AnyAction>(reducer: Reducer<S, A>, initialState: PreloadedState<S> | undefined) => { getState: () => S & { ...; }; dispatch: Dispatch<...>; subscribe(listener: () => void): Unsubscribe; replaceReducer(nextReducer: Reducer<...>): void; [Symbol.observable](): Observable<...>; }' is not assignable to type 'StoreEnhancerStoreCreator<{}, CustomProps>'.
  Call signature return types '{ getState: () => S & { meaingOfFile: number; }; dispatch: Dispatch<A>; subscribe(listener: () => void): Unsubscribe; replaceReducer(nextReducer: Reducer<S & {}, A>): void; [Symbol.observable](): Observable<...>; }' and 'Store<S & CustomProps, A>' are incompatible.
    The types of 'replaceReducer' are incompatible between these types.
      Type '(nextReducer: Reducer<S & {}, A>) => void' is not assignable to type '(nextReducer: Reducer<S & CustomProps, A>) => void'.
        Types of parameters 'nextReducer' and 'nextReducer' are incompatible.
          Types of parameters 'state' and 'state' are incompatible.
            Type '(S & {}) | undefined' is not assignable to type '(S & CustomProps) | undefined'.
              Type 'S & {}' is not assignable to type '(S & CustomProps) | undefined'.
                Type 'S & {}' is not assignable to type 'S & CustomProps'.
                  Property 'meaingOfFile' is missing in type '{}' but required in type 'CustomProps'.

不幸的是,configureStore 类型对 StoreEnhancer 没有真正有效的支持。如果您想在最后添加额外的属性,则必须使用类型转换手动添加这些属性。

在这种情况下,您可以通过使用自定义 reducer 函数包装 rootReducer 来获得相同的结果。

const rootReducer = combineReducers({
        books: BooksSlice.reducer,
        shelfs: ShelfsSlice.reducer,
    }}
const enhancedReducer = (state, action) => {
  return {
    ...rootReducer(state,action),
    meaingOfFile: 32,
  }
}

const Store = configureStore({
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(LocalStorageMiddleware),
    reducer: enhancedReducer
});