Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12111

Typescript - detecting type based on key when creating a redux reducer that takes key value pair as payload

$
0
0

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.


Viewing all articles
Browse latest Browse all 12111

Trending Articles