В Action-Reducer Mapping есть ошибка типа с несколькими типами действий - PullRequest
0 голосов
/ 19 февраля 2020

Я задал вопрос ранее сегодня , основываясь на моих попытках создать отображение между redux-action-типами и редукторами для обработки каждого из этих типов, с требованием, чтобы каждый тип действия обрабатывался явно.

Я получил отличный ответ о том, как это сделать, и теперь я могу создать такое отображение, но я получаю сообщение об ошибке, когда пытаюсь использовать его для создания редуктора.

Если у меня есть следующий код (извините, он довольно длинный, но я считаю, что это минимальный пример):

export type IActionReducerMapping<S, A extends IReduxAction<string>> = {
    [K in A['type']]: IReducer<S, Extract<A, { type: K }>>
};

interface IUser {
    id: number;
    name: string;
    age: number;
}

interface IUserState {
    [id: number]: IUser;
}

interface IAddUserAction {
    type: 'ADD_USER';
    payload: IUser;
}

interface ISetUserNameAction {
    type: 'SET_USER_NAME';
    payload: {
        id: IUser['id'];
        name: IUser['name'];
    }
}

type UserAction = IAddUserAction | ISetUserNameAction;

const mapping: IActionReducerMapping<IUserState, UserAction> = {
    'ADD_USER': (state, action) => ({
        ...state,
        [action.payload.id]: action.payload,
    }),

    'SET_USER_NAME': (state, action) => ({
        ...state,
        [action.payload.id]: {
            ...state[action.payload.id],
            name: action.payload.name,
        }
    }),
};

const userReducer = (state: IUserState, action: UserAction) => mapping[action.type](state, action);

Я получаю следующую ошибку:

Аргумент типа «UserAction» не может быть назначен параметру типа «IAddUserAction & ISetUserNameAction». Тип «IAddUserAction» не может быть назначен типу «IAddUserAction & ISetUserNameAction». Тип «IAddUserAction» нельзя назначить типу «ISetUserNameAction». Типы свойства 'type' несовместимы. Тип "ADD_USER" не может быть назначен типу "SET_USER_NAME". Ts (2345)

Я не могу видеть, где я ошибаюсь при наборе этих символов, может кто-нибудь указать где я ошибся?

Вот ссылка на игровую площадку.


Редактировать:

Следующие работы:

const userReducer = (state: IUserState, action: ISetUserNameAction | IAddUserAction) =>  {
    switch (action.type) {
        case 'ADD_USER':
            return mapping[action.type](state, action);
        case 'SET_USER_NAME':
            return mapping[action.type](state, action);
    }
}

Предположительно, потому что на этом этапе компилятор уверен, что он может знать, что тип действия и редуктор будут прекрасно работать вместе. До сих пор остается загадкой, как я могу сделать это автоматически.

1 Ответ

0 голосов
/ 19 февраля 2020

Я смог решить эту проблему, создав отдельную функцию для преобразования отображения в редуктор:

export const reducerOf = <S, A extends IReduxAction<string>>(mapping: IActionReducerMapping<S, A>) =>
    (state: S, action: A): S =>
        mapping[action.type](state, action);

Теперь я могу просто назвать его как:

const userReducer = reducerOf(mapping);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...