你如何在 redux 工具包 createSlice 中定义初始状态类型(并且类型不同)
How do you define the initial state type in redux toolkit createSlice (And the types are different)
这里有详细的记录:
Defining the Initial State Type
然而,当初始状态类型可能是多种不同类型时,问题就出现了。
import { createSlice } from "@reduxjs/toolkit";
// Type definitions
export const UNINITIALIZED = "UNINITIALIZED";
interface ICurrentCustomer {
id: string;
name: string;
}
interface ISetCurrentCustomerAction {
type: string;
payload: ICurrentCustomer;
}
// Initial state (This is intentional, null has special meaning here in my use case)
// This is the important part right here!!!!!!!!!!!!!!!!!!!!!!!
const initialState: ICurrentCustomer | typeof UNINITIALIZED | null = UNINITIALIZED;
const currentCustomerSlice = createSlice({
name: "currentCustomer",
initialState,
reducers: {
// I put any on state type here coz it will error
setCurrentCustomer: (state: any, action: ISetCurrentCustomerAction) => {
const { id, name } = action.payload;
state.id = id;
state.name = name;
return state;
},
},
});
export const { setCurrentCustomer } = currentCustomerSlice.actions;
export default currentCustomerSlice.reducer;
这里的问题是 redux 工具包会将商店中的状态类型设置为字符串。因为很明显 UNINITIALIZED 是一个字符串。这将产生错误,控制台消息为:
TypeError: Cannot create property 'id' on string 'UNINITIALIZED'
这里是关于类型推断的:
How to describe the shape of the state in createSlice
我怎样才能使上面的代码工作?
感谢任何帮助。
提前致谢。
您可以使用带有 as
的类型转换来让 createSlice
正确推断类型,如下所示:
import { createSlice } from "@reduxjs/toolkit";
// Type definitions
export const UNINITIALIZED = "UNINITIALIZED";
interface ICurrentCustomer {
id: string;
name: string;
}
interface ISetCurrentCustomerAction {
type: string;
payload: ICurrentCustomer;
}
// Define a type for your state
type State = ICurrentCustomer | typeof UNINITIALIZED | null;
// Define your initial state
const initialState: State = UNINITIALIZED;
const currentCustomerSlice = createSlice({
name: "currentCustomer",
// Do a type cast here, this will allow `createSlice` to infer the correct type
initialState: initialState as State,
reducers: {
// You can use State type here now
setCurrentCustomer: (state: State, action: ISetCurrentCustomerAction) => {
const { id, name } = action.payload;
// You will still need to check if state in `null` and `UNINITIALIZED` before accessing it
if(state!== null && state !== UNINITIALIZED) {
state.id = id;
state.name = name;
}
// Or do something like this if you want to disregard previous state
//state = {id, name};
return state;
},
},
});
export const { setCurrentCustomer } = currentCustomerSlice.actions;
export default currentCustomerSlice.reducer;
这里有详细的记录:
Defining the Initial State Type
然而,当初始状态类型可能是多种不同类型时,问题就出现了。
import { createSlice } from "@reduxjs/toolkit";
// Type definitions
export const UNINITIALIZED = "UNINITIALIZED";
interface ICurrentCustomer {
id: string;
name: string;
}
interface ISetCurrentCustomerAction {
type: string;
payload: ICurrentCustomer;
}
// Initial state (This is intentional, null has special meaning here in my use case)
// This is the important part right here!!!!!!!!!!!!!!!!!!!!!!!
const initialState: ICurrentCustomer | typeof UNINITIALIZED | null = UNINITIALIZED;
const currentCustomerSlice = createSlice({
name: "currentCustomer",
initialState,
reducers: {
// I put any on state type here coz it will error
setCurrentCustomer: (state: any, action: ISetCurrentCustomerAction) => {
const { id, name } = action.payload;
state.id = id;
state.name = name;
return state;
},
},
});
export const { setCurrentCustomer } = currentCustomerSlice.actions;
export default currentCustomerSlice.reducer;
这里的问题是 redux 工具包会将商店中的状态类型设置为字符串。因为很明显 UNINITIALIZED 是一个字符串。这将产生错误,控制台消息为:
TypeError: Cannot create property 'id' on string 'UNINITIALIZED'
这里是关于类型推断的:
How to describe the shape of the state in createSlice
我怎样才能使上面的代码工作? 感谢任何帮助。
提前致谢。
您可以使用带有 as
的类型转换来让 createSlice
正确推断类型,如下所示:
import { createSlice } from "@reduxjs/toolkit";
// Type definitions
export const UNINITIALIZED = "UNINITIALIZED";
interface ICurrentCustomer {
id: string;
name: string;
}
interface ISetCurrentCustomerAction {
type: string;
payload: ICurrentCustomer;
}
// Define a type for your state
type State = ICurrentCustomer | typeof UNINITIALIZED | null;
// Define your initial state
const initialState: State = UNINITIALIZED;
const currentCustomerSlice = createSlice({
name: "currentCustomer",
// Do a type cast here, this will allow `createSlice` to infer the correct type
initialState: initialState as State,
reducers: {
// You can use State type here now
setCurrentCustomer: (state: State, action: ISetCurrentCustomerAction) => {
const { id, name } = action.payload;
// You will still need to check if state in `null` and `UNINITIALIZED` before accessing it
if(state!== null && state !== UNINITIALIZED) {
state.id = id;
state.name = name;
}
// Or do something like this if you want to disregard previous state
//state = {id, name};
return state;
},
},
});
export const { setCurrentCustomer } = currentCustomerSlice.actions;
export default currentCustomerSlice.reducer;