如何解决Redux Toolkit TypeScript切片、Redux-Saga中间件的类型检查冲突?
这个问题其实是Redux Toolkit、TypeScript和ESLint协同工作时很常见的场景——action需要携带payload给Saga处理,但Reducer里根本用不上这个参数,两边的类型检查和代码规范就撞车了。我给你两个最常用的解决思路,都能完美解决冲突:
方案1:在Reducer中显式声明Payload但忽略它
Redux Toolkit的PayloadAction泛型可以帮你定义action的payload类型,即使你在Reducer里不用它。为了避免ESLint的未使用变量报错,你可以:
方法A:用下划线命名参数
ESLint通常会忽略以下划线开头的“有意未使用”变量:
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; const investment = createSlice({ name: 'investments', initialState, reducers: { getInvestmentsRequest(state, _payload: PayloadAction<{ term: number }>) { state.investments.status = RequestStatuses.loading; }, } })
这样TypeScript会自动生成接受{ term: number }作为参数的action creator,调用dispatch(getInvestmentsRequest({ term: product.term }))就不会报错,同时ESLint也不会揪着未使用的_payload不放。
方法B:添加ESLint忽略注释
如果团队规范不允许下划线命名,直接给未使用的payload参数加一行注释即可:
getInvestmentsRequest( state, /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ payload: PayloadAction<{ term: number }> ) { state.investments.status = RequestStatuses.loading; }
方案2:单独创建Action,用extraReducers处理状态
如果觉得在Reducer里写一个不用的参数有点别扭,你可以用Redux Toolkit的createAction单独定义这个带payload的action,然后在切片的extraReducers里处理状态变更:
import { createSlice, createAction, PayloadAction } from '@reduxjs/toolkit'; // 单独创建带payload类型的action export const getInvestmentsRequest = createAction<{ term: number }>('investments/getInvestmentsRequest'); const investment = createSlice({ name: 'investments', initialState, reducers: {}, // 这里不再定义这个action extraReducers: (builder) => { builder.addCase(getInvestmentsRequest, (state) => { // 这里不需要接收payload,ESLint和TypeScript都不会有意见 state.investments.status = RequestStatuses.loading; }); } })
这种方式更清晰,把“触发Saga的action”和“更新状态的reducer逻辑”分开,尤其当这个action主要是给Saga用,Reducer只需要做简单的loading状态切换时,非常合适。
额外优化:全局配置ESLint忽略下划线参数
如果你的项目里经常遇到这种场景,可以在ESLint配置文件中添加规则,自动忽略以下划线开头的未使用参数,不用每次手动处理:
{ "rules": { "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] } }
内容的提问来源于stack exchange,提问作者Dmitriy Glazkov

