如何为redux切片及其操作创建强类型泛型函数



我正在使用@reduxjs/toolkit,并希望创建一个易于扩展的函数,该函数使用默认的reducers创建切片。我现在拥有的实现可以工作,但不是强类型的。如何创建一个函数,使切片的操作类型不仅包含默认的减少器,还包含传入的减少器?我尝试过使用推理类型,但无法使其发挥作用。

如有任何指导,我们将不胜感激。谢谢

最小示例:在common.ts文件中(其中可以在切片之间共享逻辑(

export interface StoreState<T> {
data: T
status: 'succeeded' | 'failed' | 'idle'
error: string | null
}
// create a slice given a name and make it possible to extend reducers so they include more than just reset and updateStatus
export const createStoreSlice = <T>(props: {
sliceName: string
defaultState: T
reducers?: SliceCaseReducers<StoreState<T>> // <-- want to infer this in 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, // <--- want to somehow infer the type of this when exporting slice actions
reset: (state) => {
Object.assign(state, initialState)
},
updateStatus: (state, action) => {
state.status = action.payload
},
},
})
}

slices/<sliceName>.ts(具有额外逻辑的特定切片(中

export const genericSlice = createStoreSlice({
sliceName: 'someSliceName',
defaultState: { someField: 'some value' },
reducers: {
setSomeField: (state, action) => {
const { payload } = action
state.data.someField = payload
},
},
})
// these actions should be strongly typed from the createStoreSlice function parameters and contain the default reducers (eg. reset, updateStatus) and extra ones specific to the slice (eg. setSomeField)
export const { reset, updateStatus, setSomeField } = genericSlice.actions 

你真的很接近,但有三个部分你错过了

  1. 必须使用泛型类型推断reducers的类型
  2. 必须使用通用reducers类型(即R(和提供的ValidateSliceCaseReducers类型来确定reducers的结果类型
  3. 要求reducers类型。我只能使用所需的减速器,但可能有办法解决这个问题,但不太可能,因为类型来自@reduxjs/toolkit

注意:我刚刚将createStoreSlice道具提取到StoreSliceProps类型中,以便于阅读。

import { SliceCaseReducers, createSlice, ValidateSliceCaseReducers } from '@reduxjs/toolkit';
export interface StoreState<T> {
data: T;
status: 'succeeded' | 'failed' | 'idle';
error: string | null;
}
interface StoreSliceProps<T, R extends SliceCaseReducers<StoreState<T>>> {
sliceName: string;
defaultState: T;
reducers: ValidateSliceCaseReducers<StoreState<T>, R>;
}
export function createStoreSlice<T, R extends SliceCaseReducers<StoreState<T>>>(props: StoreSliceProps<T, R>) {
const { sliceName, reducers, defaultState } = props;
const initialState: StoreState<T> = {
data: defaultState,
status: 'idle',
error: null,
};
return createSlice({
name: sliceName,
initialState,
reducers: {
...reducers,
reset: (state) => {
Object.assign(state, initialState);
},
updateStatus: (state, action) => {
state.status = action.payload;
},
},
});
};
export const genericSlice = createStoreSlice({
sliceName: 'someSliceName',
defaultState: { someField: 'some value' },
reducers: {
setSomeField: (state, action) => {
const { payload } = action;
state.data.someField = payload;
},
},
});
export const { reset, updateStatus, setSomeField, fakeReducer } = genericSlice.actions; // only fakeReducer throws error as unknown as expected

这是一个正在工作的TS游乐场

从他们的文档中可以看到这个例子,它可以更好地解释它。

相关内容

  • 没有找到相关文章

最新更新