Immutable.js 与 React Typescript 结合

Posted

技术标签:

【中文标题】Immutable.js 与 React Typescript 结合【英文标题】:Immutable.js Combine with React Typescript 【发布时间】:2021-07-01 02:47:33 【问题描述】:

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

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 是一个带有 getter 和 setter 等的映射,无论您在其中存储什么数据。我猜你的状态必须是defaultState : Immutable.Map&lt;string, any&gt; 【参考方案1】:

有多种方法可以构造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 函数上设置一个泛型。如您所见,第二个重载是唯一一个只有&lt;V&gt; 而不是&lt;K, V&gt; 的重载。所以你可以通过为Map 设置一个值类型来匹配这个重载。在这种情况下DashboardState 的值类型是any

state = Map<any>(defaultState)

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

我建议使用官方的Redux Toolkit,它具有强大的打字稿支持以及使用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;
   

【讨论】:

Paist 感谢您的解释。我更新了我的代码并将类型添加到默认状态并键入了 Map 构造函数。我不确定我是否理解如何解决这个问题,因为我仍然遇到同样的错误。你能写任何例子,也许我会更好地理解它? export default function (state = Map&lt;number | null&gt;(defaultState), action): Map&lt;string, number | null&gt; 并从 defaultState 中删除类型。但是您应该使用undefined 而不是null,因为Map.get() 包括undefined。实际上你应该只使用 Redux Toolkit :)

以上是关于Immutable.js 与 React Typescript 结合的主要内容,如果未能解决你的问题,请参考以下文章

将 Flux 存储中的 Immutable.js 映射与内部 React 组件状态合并

在 Immutable.js 中使用 React 的不可变助手

React+Immutable.js的心路历程

使用 immutable.js 的 react shouldComponentUpdate 的最佳实现是啥

大话immutable.js

大话immutable.js