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;
}
}
我很难将我的减速器重构为 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;
}
}