Подробности
Я пытаюсь создать вспомогательную функцию, чтобы объединить мои редукторы, чтобы иметь глобальный редуктор для использования с useReducer
ловушкой реагирования и контекстным API. У меня есть работающая функциональность, но в настоящее время я не доволен проверкой типов.
Проблема
Чтобы она работала, мне пришлось добавить [key: string]: Reducer<any>
в тип Редукторы и [key: string]: any;
в типе GlobalState. Если я их удаляю, я получаю ошибки
Элемент неявно имеет тип 'any', потому что выражение типа 'string' нельзя использовать для индексации типа 'GlobalState'. Для типа «GlobalState» не найдено сигнатуры индекса с параметром типа «строка».
Элемент неявно имеет тип «любой», поскольку выражение типа «строка» нельзя использовать для индексации типа «Редукторы» ». Нет подписи индекса с параметром типа 'string' для типа 'Reducers'.
Это оставляет меня с функцией combineReducers
, где я могу присвоить ключу состояния любое имя
Пример
У меня есть начальное состояние, подобное этому: {page: {some state}, state2: {some state}}
, и затем я объединяю редукторы, как это: combineReducers({ pages: pageReducer, state3: reducer2 });
Теперь у меня будет состояние выглядит как {page: {some state}, state2: {some state}}, pages: {some state}, state3: {some state}
из-за «случайного» наименования ключей состояния неправильно.
Вопрос
Есть ли способ заставить это работать при удалении [key: string]: Reducer<any>
в тип Редукторы и [key: string]: any;
в типе GlobalState?
Код
types.ts
export type GlobalReducer = (state: GlobalState, action: Action) => GlobalState;
export type Reducer<State> = (state: State, action: Action) => State;
export type Reducers = {
[key: string]: Reducer<any>;
page: Reducer<PageState>;
state2: Reducer<AnotherState>;
};
export type GlobalState = {
[key: string]: any;
page: PageState;
state2: AnotherState;
};
export type PageState = {
title: string;
loading: true;
};
export type AnotherState = {
hello: string;
};
combReducers.ts
import _ from "lodash";
import { Action, Reducers, GlobalState, GlobalReducer } from "./types";
const combineReducers = (reducers: Reducers): GlobalReducer => {
return (state: GlobalState, action: Action): GlobalState => {
const reducerKeys = Object.keys(reducers);
reducerKeys.forEach((key) => {
const newState = reducers[key](state[key], action);
state = _.isEqual(newState, state[key]) ? state : { ...state, [key]: newState };
});
return state;
};
};
export { combineReducers };
index.ts
export const globalReducer = combineReducers({ page: pageReducer, state2: reducer2 });
initialState.ts
export const initialState: GlobalState = {
page: {
title: "Holidaze",
loading: true
},
state2: {
hello: ""
}
};