我正在尝试使用Redux工具包createAction
来生成一个采用泛型类型的操作。类型如下。
export interface ObjectArray {
externalId: string
}
export interface CarFilters {
arrayType: string[];
objectType: ObjectArray[];
}
export type FilterOptionValue = string | number;
export type FilterMapValue = FilterOptionValue[] | string;
export interface ShipFilters {
[key: number]: FilterMapValue;
}
type AppliedFiltersType = {
cars: CarFilters;
ships: ShipFilters;
}
type PathValue<T extends object, K extends keyof T = keyof T> = T[K] extends unknown ? T[K] : never;
export type AssingValueType<
Category extends keyof AppliedFiltersType = keyof AppliedFiltersType,
Key extends keyof PathValue<AppliedFiltersType, Category> = keyof PathValue<AppliedFiltersType, Category>
> = {
category: Category,
filterKey: Key
value: PathValue<AppliedFiltersType[Category], Key>;
}
减速器和动作
import { createAction, createReducer } from "@reduxjs/toolkit";
import { AssingValueType, AppState } from "./types";
export const updateAppliedFilterValue = createAction<AssingValueType>(
"UPDATE_APPLIED_FILTER_VALUE"
);
const initialState = {
appliedFilters: {
cars: {
arrayType: [],
objectType: []
},
ships: {}
}
} as AppState;
const reducerCreator = createReducer(initialState, (builder) => {
builder.addCase(updateAppliedFilterValue, (state, action) => {
state.appliedFilters[action.payload.category] = action.payload.value;
});
});
export default reducerCreator;
目的是对操作参数进行严格的类型检查,这样就不能用不一致的类型调用它。
例如
更新AppliedFilterValue({类别:'汽车',filterKey:1,值:3})
应标识为ts编译器的错误。
纯功能如以下作品
const updateFilterValues = <Category extends keyof AppliedFiltersType, Key extends keyof PathValue<AppliedFiltersType, Category>>(params: AssingValueType<Category, Key>) => {
return params;
}
但我不清楚如何使用createAction
创建生成操作我在创建推断泛型类型的操作时遇到了问题。
Codesandbox链接
您遇到的问题似乎与AssigningValueType的定义密切相关。
解决方案:
export type AssingValueType = {
[Category in keyof AppliedFiltersType]:
{ category: Category } & {
[Key in keyof AppliedFiltersType[Category]]: {
filterKey: Key,
value: PathValue<AppliedFiltersType[Category], Key>
}
}[keyof AppliedFiltersType[Category]]
}[keyof AppliedFiltersType]
讲解员AssingValueType
是判别并集类型,Category
是AppliedFiltersType的关键字,又称'ships' | 'cars'
。
对于每个潜在类别,我们也以类似的方式定义filterKey
。value
可以相对于Category和Key进行定义。
&
类型的交集运算符用于将{filterKey,value}与{category}合并。
最后也是最重要的一步是{[Category in keyof AppliedFiltersType]: ...}[keyof AppliedFiltersType]
其提取AppliedFiltersType的每个键的并集类型。
简而言之。。。{ships: {category: 'ships', ...}, cars: {category: 'cars', ...}}
变为{category: 'cars' ...} | {category: 'ships'}
关于你最初的担忧,createAction
应该像你想要的那样发挥魅力。