Я пытался создать своего рода сопоставление с шаблоном в машинописи, особенно здесь, для создания редукторов Redux.
Я бы очень хотел иметь возможность заранее указать, что редуктор должен обрабатывать все действия определенного типа. Я попытался сделать это, создав объект, который имеет ключ по типу действия, со значениями, которые являются редукторами. Типы для этого отображения выглядят так:
export interface IReduxAction<T> {
type: T;
}
interface IReducer<S, A> {
(state: S, action: A): S;
}
export type IActionReducerMapping<S, A extends IReduxAction<string>> = Record<A['type'], IReducer<S, A>>;
Это делает большую часть того, что я планировал; любое отображение, созданное для данного типа действия, должно реализовывать все типы действий. Проблема в том, что, как я настроил типизацию, редукторы в отображении не могут определить точный тип их действия. Например:
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> = {
// here action is only aware of the properties on UserAction
// ideally it'd know that it has access to the properties of
// IAddUserAction
'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,
}
}),
};
Проблема состоит в том, что действие в каждом редукторе является только объединением типа UserAction, и поэтому, например, age не доступен. Есть ли способ настроить типизацию с таким типом шаблона, чтобы:
- Я мог гарантировать, что все типы действий обрабатываются, так или иначе
- Я могу настроить редукторы, которые знают тип действия им дан