Newish to Typescript. I and moving a project to TS and I am struggling to define the Typescript for my reducers when creating a slice using redux-toolkit. The scenario is I have filters stored in a state. I have a query string and an object of fields that will be filtered if a value is present. The type of each field depends on the data stored in that field. To set a field filter value I have created a reducer that accepts a key and value pair as the payload. I then use that to set the filter value for that field. After all of my Googling, ChatGPTing and Gemini-ing I am still getting the following error.
Type 'string | string[]' is not assignable to type 'string[] & string'. Type 'string' is not assignable to type 'string[] & string'. Type 'string' is not assignable to type 'string[]'.ts(2322)(property) filters: WritableDraft<FilterValues>
This is the code for the slice. I have tried multiple types for the payload of setFilter and removeFilter and have left two of the setFilters to show what I have tried.
import { PayloadAction, createSelector, createSlice } from '@reduxjs/toolkit';import { RootState } from "redux/store";export type FilterValues = { tags_map: string[]; reference: string; time_executed: string; type: string;}interface State { filterQuery: string; filters: FilterValues;}const initialState:State = { filterQuery: '', filters: { tags_map: [], reference: '', time_executed: '', type: '', },};type KeyValuePayload<T> = { [K in keyof T]: { key: K; value: T[K] }}[keyof T];export const slice = createSlice({ name: 'filters', initialState, reducers: { setFilterQuery: (state, { payload }) => { state.filterQuery = payload }, // setFilter : (state, { payload }: PayloadAction<{ key: keyof FilterValues, value: FilterValues[keyof FilterValues] }>) => { // state.filters[payload.key] = payload.value // }, setFilter : (state, { payload }: PayloadAction<KeyValuePayload<FilterValues>>) => { const { key, value } = payload state.filters[key] = value }, removeFilter: (state, { payload }: PayloadAction<keyof FilterValues>) => { state.filters[payload] = initialState.filters[payload] }, removeAllFilters: (state) => { return { ...state, filters: initialState.filters } }, },});export const { setFilterQuery, setFilter, removeFilter, removeAllFilters,} = slice.actions;export default slice. Reducer;
Sample payload
setFilter({key: "reference", value: "foobar"})setFilter({key: "tags_map", value: ["foo", "bar"]})
I am at a loss. I used the approach explained in this answer, and trying it in TS playground it infers the correct types. But it I am still getting errors. I am sure there is a simple answer to this.
Thank you in advance.