如何创建通用Redux Slice更新嵌套initialState对象?
解决Redux Toolkit通用Slice的TypeScript类型自动收窄问题
核心问题是你当前代码里的section和varName是独立的字符串类型,TypeScript无法建立两者的关联关系,导致switch分支里无法自动收窄类型。解决关键是用**区分联合类型(Discriminated Union)**把section、varName和对应值类型绑定起来,让TypeScript能自动推导类型。
具体实现步骤
- 定义关联的联合类型
先把每个section对应的字段名和值类型绑定成联合类型,让TypeScript明确不同section对应的合法字段和值:
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; // 定义嵌套结构的子类型 interface User { name: string; age: number; } interface Settings { theme: string; notifications: boolean; } // 根状态类型 interface AppState { user: User; settings: Settings; } const initialState: AppState = { user: { name: '', age: 0 }, settings: { theme: 'light', notifications: true }, }; // 定义区分联合类型,绑定section、字段名和对应值的类型 type UpdateNestedPayload = | { section: 'user'; varName: keyof User; value: User[keyof User] } | { section: 'settings'; varName: keyof Settings; value: Settings[keyof Settings] };
- 在Slice的Reducer中使用该类型
在reducer的action payload里使用上面定义的联合类型,此时switch分支中TypeScript会自动根据section的值收窄varName和value的类型,无需as断言:
const appSlice = createSlice({ name: 'app', initialState, reducers: { updateNestedField: (state, action: PayloadAction<UpdateNestedPayload>) => { const { section, varName, value } = action.payload; switch (section) { case 'user': // varName自动收窄为keyof User,value自动匹配对应字段类型 state.user[varName] = value; break; case 'settings': // 同理,类型自动收窄 state.settings[varName] = value; break; } }, }, }); export const { updateNestedField } = appSlice.actions; export default appSlice.reducer;
为什么这种方式有效?
区分联合类型通过一个共同的判别字段(这里是section),让TypeScript能在分支判断时自动推导其他字段的类型。当你在switch里判断section === 'user'时,TypeScript会自动知道当前payload属于联合类型中section: 'user'的分支,进而varName只能是User的键,value也必须匹配对应键的类型。
如果你的嵌套结构更复杂(比如多层嵌套),可以基于这个思路扩展递归的联合类型,但上述方案已经能解决绝大多数常见的嵌套状态更新场景。
内容的提问来源于stack exchange,提问作者Ashylen
相关产品推荐
相关产品推荐

