我试图在打字稿中创建一种模式匹配,尤其是在这里,用于创建Redux reducer。
我真的很想能够提前指定一个减速器必须处理特定类型的所有动作。我试图通过创建一个由操作类型作为键的对象来实现此目的,该对象的值是reduce。此映射的类型如下:
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,因此无法访问年龄。有没有一种方法可以设置这种类型的键入,例如:
答案 0 :(得分:1)
您可以通过使用自定义映射类型来解决action
类型不正确的问题,该自定义映射类型可以映射所有类型(A['type']
)并使用Extract
条件类型获取每种类型名称的正确操作类型。
export type IActionReducerMapping<S, A extends IReduxAction<string>> = {
[K in A['type']]: IReducer<S, Extract<A, { type: K }>>
};