Я пытаюсь набрать редуктор более высокого порядка, и мне удалось сузить проблему, проблема заключается в state
введите redux
определение типа Reducer
, что S | undefined
, Если я удаляю undefined
и просто набираю state
как S
все работает как положено
export type Reducer<S = any, A extends Action = AnyAction> = (
state: S | undefined,
action: A
) => S
Проблема в том, что редуктор более высокого порядка не инициализирует состояние со значением по умолчанию, которое требуется redux
, так как оно отправляет действие, которое не соответствует ни в одном редукторе, для заполнения хранилища начальным значением, но я предполагаю, что машинопись не может сказать, что внутренний редуктор справится с этим.
Какие у меня варианты здесь кроме удаления undefined из определения типа?
Тип mov ie в src > reducers.ts > RootState
внизу never
Песочница
Редуктор высшего порядка
import { Action } from "redux";
const startReducer = <S>(state: S): S => ({
...state,
loading: true,
error: false
});
const successReducer = <S>(state: S): S => ({
...state,
loading: false
});
const errorReducer = <S>(state: S): S => ({
...state,
error: true,
loading: false
});
type LoadingActionTypes = Record<"start" | "success" | "error", string>;
const withLoadingStates = ({ start, success, error }: LoadingActionTypes) => {
const actionReducerMapper = {
[start]: startReducer,
[success]: successReducer,
[error]: errorReducer
};
return <S, A extends Action>(baseReducer: (state: S, action: A) => S) => (
state: S,
action: A
): S => {
const nextState = actionReducerMapper[action.type]
? actionReducerMapper[action.type](state)
: state;
return baseReducer(nextState, action);
};
};
export default withLoadingStates;
Внутренний редуктор
import { combineReducers } from "redux";
import withLoadingStates from "./withLoadingStates";
const FETCH_MOVIE_BY_ID_START = "FETCH_MOVIE_BY_ID_START";
const FETCH_MOVIE_BY_ID_SUCCESS = "FETCH_MOVIE_BY_ID_SUCCESS";
const FETCH_MOVIE_BY_ID_ERROR = "FETCH_MOVIE_BY_ID_ERROR";
type FetchMovieByIdStartAction = { type: typeof FETCH_MOVIE_BY_ID_START };
type FetchMovieByIdSuccessAction = { type: typeof FETCH_MOVIE_BY_ID_SUCCESS };
type FetchMovieByIdErrorAction = { type: typeof FETCH_MOVIE_BY_ID_ERROR };
type MovieByIdActionTypes =
| FetchMovieByIdStartAction
| FetchMovieByIdSuccessAction
| FetchMovieByIdErrorAction;
type LoadingStates = {
loading: boolean;
error: boolean;
};
const initialState: LoadingStates = {
loading: false,
error: false
};
const movieReducer = (state = initialState, action: MovieByIdActionTypes) =>
state;
const wrappedReducer = withLoadingStates({
start: FETCH_MOVIE_BY_ID_START,
success: FETCH_MOVIE_BY_ID_SUCCESS,
error: FETCH_MOVIE_BY_ID_ERROR
})(movieReducer);
export const rootReducer = combineReducers({
movie: wrappedReducer
});
// movie type is never
export type RootState = ReturnType<typeof rootReducer>;
Ошибка, которую я получаю
(свойство) mov ie: Редуктор Без перегрузки соответствует этому вызову. Перегрузка 1 из 2, '(redurs: ReducersMapObject <{mov ie: LoadingStates; trending: Record;}, any>): Reducer <...>', вызвала следующую ошибку. Тип '(состояние: LoadingStates, action: MovieByIdActionTypes) => LoadingStates' нельзя назначить типу 'Reducer'. Типы параметров «состояние» и «состояние» несовместимы. Тип 'LoadingStates | undefined »нельзя назначить типу« LoadingStates ». Тип 'undefined' нельзя назначить типу 'LoadingStates'.ts (2769)