Immutable.js 结合 React Typescript

Immutable.js Combine with React Typescript

我很难将我的减速器重构为 TS,因为我在我的项目中使用 Immutable.js 这是我的减速机:

export interface DashboardState {
   componentId: number | null;
   dashboard: number | null;
}

let defaultState: DashboardState = {
   componentId: null,
   dashboard: null,
};

export default function (state = Map<string, number>(defaultState), action):  
Map<string, number> {
    switch (action.type) {
        case dashboardsActionsTypes.SET_PROJECT_VIEW:
            return state.set('componentId', action.payload);
        case dashboardsActionsTypes.SET_DASHBOARD_TYPE:
            return state.set('dashboard', action.payload);
        default:
            return state;
    }
}

我在 Map(defaultState) 上收到一条错误消息:

我在这里缺少什么?

谢谢

有多种方法可以构建 Map

export function Map<K, V>(collection: Iterable<[K, V]>): Map<K, V>;
export function Map<V>(obj: {[key: string]: V}): Map<string, V>;
export function Map<K, V>(): Map<K, V>;
export function Map(): Map<any, any>;

第一次重载时的错误是预料之中的,因为您绝对不应该匹配那个。您的对象更接近第二个重载,但您不会自动匹配该重载,因为它涉及 DashboardState 没有的 string 索引签名。

此处快速而肮脏的解决方案涉及在 Map 函数上设置泛型。如您所见,第二个重载是唯一一个只有 <V> 而不是 <K, V> 的重载。因此,您可以通过为 Map 设置值类型来匹配此重载。在这种情况下,DashboardState 的值类型是 any.

state = Map<any>(defaultState)

此设置的类型支持非常薄弱。 state 的键可以是任何 string,值可以是任何东西。如果您无法从中获得任何有用的信息,为什么还要费心使用 Typescript?

我推荐使用官方Redux Toolkit which has strong typescript support as well as support for immutability using Immer。并将 DashboardState 中的 any 替换为实际类型。


编辑:

查看您的编辑后,我建议您使用可选属性 (number | undefined) 而不是 number | null,因为 Map.get() 包括 undefined 以及预期值。所以你会得到 number | null | undefined。如果使用可选属性,那么您实际上根本不需要初始状态。您可以使用空 Map.

我们也可以将键限制为DashboardState.

的键

在任何状态类型上使用这些实用程序:

export type MapOf<T> = Map<keyof T, T[keyof T]>;

const createMap = <T,>(): MapOf<T> => Map<keyof T, T[keyof T]>();

对于仪表板:

export interface DashboardState {
  componentId?: number;
  dashboard?: number;
}

export default function (state = createMap<DashboardState>(), action): MapOf<DashboardState> {
   switch (action.type) {
       case dashboardsActionsTypes.SET_PROJECT_VIEW:
           return state.set('componentId', action.payload);
       case dashboardsActionsTypes.SET_DASHBOARD_TYPE:
           return state.set('dashboard', action.payload);
       default:
           return state;
   }
}