You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux与TypeScript中如何实现set action的键值严格类型约束

解决方案

你当前写法的核心问题是PayloadAction里的key和value类型没有做绑定:key: keyof MyState仅约束key是状态键之一,value: any跳过了所有类型校验,TS无法根据传入的key推导对应value的合法类型。
要实现严格的键值类型匹配,只需要构造一个键值绑定的联合类型作为payload类型即可,不需要改动reducer的运行逻辑。


方式1:默认对象传参调用

如果你保持Redux默认的action调用形式(传入单个payload对象),实现代码如下:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface MyState {
  key1: string;
  key2: boolean;
  key3: number;
}

// 构造键值一一绑定的payload联合类型
type SetStatePayload<T> = {
  [K in keyof T]: {
    key: K;
    value: T[K];
  };
}[keyof T];

const initialState: MyState = {
  key1: '',
  key2: false,
  key3: 0,
};

const testSlice = createSlice({
  name: 'test',
  initialState,
  reducers: {
    set: (state, action: PayloadAction<SetStatePayload<MyState>>) => {
      const { key, value } = action.payload;
      state[key] = value;
    },
  },
});

const { set } = testSlice.actions;

// 校验效果
set({ key: 'key1', value: 1 }); // 类型报错:value类型应为string
set({ key: 'key1', value: 'my string value' }); // 校验通过
set({ key: 'key2', value: true }); // 校验通过
set({ key: 'key2', value: 'my string value' }); // 类型报错:value类型应为boolean

方式2:双参数调用(匹配你给出的示例写法)

如果你想直接传入key、value两个参数调用action(不需要包一层payload对象),可以通过prepare回调组装payload,同时保留类型校验:

const testSlice = createSlice({
  name: 'test',
  initialState,
  reducers: {
    set: {
      reducer: (state, action: PayloadAction<SetStatePayload<MyState>>) => {
        const { key, value } = action.payload;
        state[key] = value;
      },
      // 对入参做泛型约束,和你找到的setAttribute类型逻辑一致
      prepare: <K extends keyof MyState>(key: K, value: MyState[K]) => {
        return { payload: { key, value } };
      },
    },
  },
});

const { set } = testSlice.actions;

// 校验效果和你预期完全一致
set('key1', 1); // 类型报错:value类型应为string
set('key1', 'my string value'); // 校验通过
set('key2', true); // 校验通过(注:你示例中写的传入boolean是笔误,boolean是TS类型,运行时应传入true/false布尔值)
set('key2', 'my string value'); // 类型报错:value类型应为boolean

实现原理

我们通过映射类型遍历MyState的所有键,生成每个键对应{key: 键名, value: 对应值类型}的结构,再通过索引访问[keyof T]把所有结构合并成联合类型。TS会根据你传入的key自动收窄联合类型的范围,匹配对应value的合法类型,实现严格校验。
你找到的setAttribute函数的泛型逻辑,本质和这里的类型约束思路一致,只是Redux的action payload需要先把键值组装成对象,所以我们提前把所有合法的键值组合做成了联合类型。

内容的提问来源于stack exchange,提问作者Daniel Aviv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:06:24