Как правильно использовать PayloadAction с метатипом в redux-toolkit?
Упрощенный пример
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
type Cake = {
flavor: string;
size: 'S' | 'M' | 'L';
};
const initialState: { all: Cake[]; meta: { currentPage: number } } = {
all: [],
meta: {
currentPage: 0,
},
};
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
fetchAll(
state,
action: PayloadAction<Cake[], string, { currentPage: number }>,
) {
state.all = action.payload;
state.meta = action.meta;
},
},
});
export default cakeSlice;
Я получаю эти ошибки.
Type '
(state: {
all: {
flavor: string;size: "S" | "M" | "L";
} [];meta: {
currentPage: number;
};
}, action: PayloadAction < Cake[], string, {
currentPage: number;
}, never > ) => void ' is not assignable to type '
CaseReducer < {
all: Cake[];meta: {
currentPage: number;
};
}, {
payload: any;type: string;
} > | CaseReducerWithPrepare < {
all: Cake[];meta: {
currentPage: number;
};
}, {
payload: any;type: string;
} > '
Type '
(state: {
all: {
flavor: string;size: "S" | "M" | "L";
} [];meta: {
currentPage: number;
};
}, action: PayloadAction < Cake[], string, {
currentPage: number;
}, never > ) => void '
is not assignable to type 'CaseReducer<{ all: Cake[]; meta: { currentPage: number; }; }, { payload: any; type: string; }>'.
Types of parameters 'action'
and 'action'
are incompatible.
Type '{ payload: any; type: string; }'
is not assignable to type 'PayloadAction<Cake[], string, { currentPage: number; }, never>'.
Property 'meta'
is missing in type '{ payload: any; type: string; }'
but required in type '{ meta: { currentPage: number; }; }
'.
1 ответ
Решение
По умолчанию RTK создает создателя действия только с одним аргументом и только свойством полезной нагрузки. Это поведение нельзя изменить с помощью аннотаций TS, поскольку аннотации TS не влияют на поведение во время выполнения.
Вы можете использовать prepare
обозначение для определения функции, которая отменяет это поведение по умолчанию. Эта функция имеет ту же сигнатуру и поведение, что и prepare
аргумент для createAction, поэтому вы можете найти там большую часть соответствующей документации.
В вашем конкретном случае вам нужно что-то вроде
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
fetchAll: {
reducer(
state,
action: PayloadAction<Cake[], string, { currentPage: number }>
) {
state.all = action.payload
state.meta = action.meta
},
prepare(payload: Cake[], currentPage: number) {
return { payload, meta: { currentPage } }
}
}
}
})
Вот как машинописная площадка