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

如何为Redux切片及动作创建强类型泛型函数?

问题描述

我正在使用@reduxjs/toolkit,希望创建一个可扩展的函数,用于生成带有默认reducer的Redux切片。当前实现可正常运行,但不具备强类型特性。如何创建该函数,使切片的actions类型既包含默认reducer,又包含传入的自定义reducer?我尝试过类型推断,但未成功实现。

最小示例

common.ts(切片共享逻辑)

export interface StoreState<T> {
  data: T
  status: 'succeeded' | 'failed' | 'idle'
  error: string | null
}

// 创建切片并支持扩展reducer,不止包含reset和updateStatus
export const createStoreSlice = <T>(props: {
  sliceName: string
  defaultState: T
  reducers?: SliceCaseReducers<StoreState<T>> // <-- 希望在slices/<sliceName>.ts中推断此类型
}) => {
  const { sliceName, reducers, defaultState } = props

  const initialState: StoreState<T> = {
    data: defaultState,
    status: 'idle',
    error: null,
  }

  return createSlice({
    name: sliceName,
    initialState,
    reducers: {
      ...reducers, // <--- 导出切片actions时希望能推断此类型
      reset: (state) => {
        Object.assign(state, initialState)
      },
      updateStatus: (state, action) => {
        state.status = action.payload
      },
    },
  })
}

slices/.ts(带额外逻辑的特定切片)

export const genericSlice = createStoreSlice({
  sliceName: 'someSliceName',
  defaultState: { someField: 'some value' },
  reducers: {
    setSomeField: (state, action) => {
      const { payload } = action
      state.data.someField = payload
    },
  },
})

// 这些actions应从createStoreSlice参数获取强类型,包含默认reducer(如reset、updateStatus)和切片专属reducer(如setSomeField)
export const { reset, updateStatus, setSomeField } = genericSlice.actions 
解决方案

要实现强类型支持,需要让createStoreSlice正确推断自定义reducers的类型,并与默认reducers的类型合并。核心是通过泛型参数捕获自定义reducers类型,结合Redux Toolkit内置类型完成类型合并。

修改后的common.ts代码如下:

import { createSlice, SliceCaseReducers, Slice } from '@reduxjs/toolkit'

export interface StoreState<T> {
  data: T
  status: 'succeeded' | 'failed' | 'idle'
  error: string | null
}

// 定义默认reducers的明确类型
type DefaultReducers<T> = {
  reset: (state: StoreState<T>) => void
  updateStatus: (state: StoreState<T>, action: { payload: StoreState<T>['status'] }) => void
}

// 添加泛型R捕获自定义reducers类型,默认值为空对象支持无自定义reducers场景
export const createStoreSlice = <T, R extends SliceCaseReducers<StoreState<T>> = {}>(props: {
  sliceName: string
  defaultState: T
  reducers?: R
}): Slice<StoreState<T>, R & DefaultReducers<T>> => {
  const { sliceName, reducers, defaultState } = props

  const initialState: StoreState<T> = {
    data: defaultState,
    status: 'idle',
    error: null,
  }

  const defaultReducers: DefaultReducers<T> = {
    reset: (state) => {
      Object.assign(state, initialState)
    },
    updateStatus: (state, action) => {
      state.status = action.payload
    },
  }

  return createSlice({
    name: sliceName,
    initialState,
    reducers: {
      ...reducers,
      ...defaultReducers,
    } as R & DefaultReducers<T>, // 类型断言确保合并后的reducers类型合法
  })
}

关键说明

  • 新增泛型参数R用于捕获传入的自定义reducers类型,默认值设为空对象,兼容不传入自定义reducers的场景。
  • 定义DefaultReducers<T>明确默认reducers的参数和返回值类型,避免类型模糊。
  • 返回类型指定为Slice<StoreState<T>, R & DefaultReducers<T>>,让切片的actions自动合并自定义与默认reducers的类型。
  • 通过as R & DefaultReducers<T>进行类型断言,消除TypeScript对合并后reducers类型的校验报错。

修改后,在slices/<sliceName>.ts中,genericSlice.actions会自动包含reset、updateStatus和setSomeField的强类型,解构时不会出现类型错误,且每个action的payload类型也会被正确推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:48:22