【问题标题】:Redux toolkit createAction with generic type具有泛型类型的 Redux 工具包 createAction
【发布时间】:2021-10-24 22:20:37
【问题描述】:

我正在尝试使用 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;

目的是使动作参数严格类型检查,所以它不能被不一致的类型调用。

例如

updateAppliedFilterValue({ 类别:“汽车”, 过滤键:1, 值:3 })

应该被 ts 编译器识别为错误。

像下面这样的纯函数工作

const updateFilterValues = <Category extends keyof AppliedFiltersType, Key extends keyof PathValue<AppliedFiltersType, Category>>(params: AssingValueType<Category, Key>) => {

  return params;
}

但我不清楚如何使用createAction 创建生成操作 我无法创建推断泛型类型的操作。

Codesandbox Link

【问题讨论】:

    标签: reactjs typescript generics redux redux-toolkit


    【解决方案1】:

    您遇到的问题似乎与 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]
    

    解释器 AssingValueTypeDiscriminated Union TypeCategory 的一个 keyof AppliedFiltersType aka 'ships' | 'cars'

    对于每个潜在的类别,我们还以类似的方式定义filterKeyvalue 可以相对于 Category 和 Key 来定义。

    &amp; type intersection operator 用于将 { filterKey, value } 与 { category } 合并。

    最后也是最重要的一步是 {[Category in keyof AppliedFiltersType]: ...}[keyof AppliedFiltersType] 它为 AppliedFiltersType 的每个键提取联合类型。

    总之... {ships: {category: 'ships', ...}, cars: {category: 'cars', ...}} 变为 {category: 'cars' ...} | {category: 'ships'}

    关于您最初的担忧,createAction 应该像您打算使用它的方式一样发挥魅力。

    【讨论】:

    • 确实它像 char.m 一样工作。那是转储复制/粘贴。我仍然需要理解它。还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2020-03-27
    • 1970-01-01
    相关资源
    最近更新 更多