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

TypeScript:如何为Reducer的set_value动作推断动态键值类型?

Solution for Type-Safe set_value Action Payload

To create a type-safe payload for your set_value action that adapts to any key in IState and enforces the correct value type, you can use TypeScript mapped types with either a union payload type or a generic action approach. Here's how to implement both solutions:

1. Union Payload Type (Direct Action Definition)

First, define a payload type that is a union of all valid single-key objects from IState:

interface IState {
  car_brand: string;
  year: number;
  // Add other properties here
}

enum ACTION_TYPE {
  set_value = 'set_value',
}

// Create a union type where each member is an object with one key from IState and its matching value type
type SetValuePayload = {
  [K in keyof IState]: { [Key in K]: IState[Key] }
}[keyof IState];

// Define the action type using the union payload
type IAction = {
  type: ACTION_TYPE.set_value;
  payload: SetValuePayload;
};

How This Works:

  • SetValuePayload iterates over every key in IState, creates a type for each key-value pair, then converts this mapped type into a union of those single-key objects.
  • For example, if IState has car_brand (string) and year (number), SetValuePayload becomes { car_brand: string } | { year: number }.
  • TypeScript will block invalid payloads (like passing a string for year) automatically.

2. Generic Action Type with Helper Function (Better for Action Creation)

For more intuitive action creation with automatic type inference, use a generic action type paired with a helper function:

interface IState {
  car_brand: string;
  year: number;
  // Add other properties here
}

enum ACTION_TYPE {
  set_value = 'set_value',
}

// Generic action type tied to a specific key K from IState
type IAction<K extends keyof IState> = {
  type: ACTION_TYPE.set_value;
  payload: { [Key in K]: IState[Key] };
};

// Helper function to create type-safe set_value actions
function setValue<K extends keyof IState>(key: K, value: IState[K]): IAction<K> {
  return {
    type: ACTION_TYPE.set_value,
    payload: { [key]: value } as { [Key in K]: IState[Key] },
  };
}

How This Works:

  • The generic IAction<K> links the payload's key and value type directly to a specific property in IState.
  • The setValue helper infers the key type from your input, so you get instant type checks:
    • setValue('car_brand', 'Toyota') is valid (string value for string key).
    • setValue('year', '2023') throws a TypeScript error (expected number, got string).

Reducer Implementation

Whichever approach you choose, the reducer can handle the action by extracting the key from the payload and updating the state:

function reducer(state: IState, action: IAction<keyof IState> | IAction): IState {
  switch (action.type) {
    case ACTION_TYPE.set_value:
      // Extract the single valid key from the payload
      const [key] = Object.keys(action.payload) as [keyof IState];
      return {
        ...state,
        [key]: action.payload[key],
      };
    default:
      return state;
  }
}

Key Notes:

  • Our payload types enforce exactly one key-value pair, so Object.keys(action.payload)[0] will always return a valid key from IState.
  • The type assertion as [keyof IState] tells TypeScript the extracted key is a valid property of IState.

This setup ensures full type safety for modifying any property in IState with your set_value action.

内容的提问来源于stack exchange,提问作者Colin Turner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:16:07