1

Hello I have a problem I get an error as in title - expresion of type string cant be used to index type 'WritableDraft'. I would like to make it dynamic to avoid many "if" statements. Why it does not work state[action.payload.filterName]

after updating type definition, filterName: keyOf InitialState I get an error

Property 'push' does not exist on type 'string | string[] | WritableDraft<Recipe>[] | WritableDraft<{ recipes: Recipe[]; totalAmount: number; }>'.
  Property 'push' does not exist on type 'string'.

in a line:

addFilters(state, action: PayloadAction<FilteringConfiguration>) {
      state[action.payload.nameOfFilter].push(action.payload.content);
    },



filtering type: 

export type FilteringConfiguration = {
  content: string;
  type: typeOfFiltering;
  set: boolean;
  filterName: key of InitialState;
};

component: 
const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    const content = e.target.value;
    dispatch(
      recipeAction.setFilters({
        type: props.type,
        set: e.target.checked,
        content: content,
        filterName: "filterTypes",
      })
    );
  };



 redux toolkit
    
  

      const INITIAL_VALUE: InitialState = {
  recipes: [],
  likedRecipes: {
    recipes: [],
    totalAmount: 0,
  },
  recipeTypes: ["Breakfast", "Lunch", "Dinner", "Supper"],
  recipeTime: [
    "Very short (~30min)",
    "short (~1hr)",
    "medium (~3hrs)",
    "Long (~6hrs)",
  ],

  // variables for filtering recipes
  recipeTitle: "",
  filterTypes: [],
  filterLengths: [],
};
    
    const recipeSlice = createSlice({
      name: "recipe",
      initialState: INITIAL_VALUE,
      reducers: { 
    
    addFilters(state, action: PayloadAction<FilteringConfiguration>) {
      state[action.payload.filterName].push(action.payload.content);
    }, // there is an error
Kay
  • 591
  • 1
  • 7
  • 27
  • What is the shape of your ```payload``` and ```payload.filterName```? – Mod3rnx Feb 15 '22 at 13:25
  • it is 'filterName: string'. The problem is I can not assign string as index types. How to solve it? – Kay Feb 15 '22 at 13:40
  • You have shape and type of it as FilteringConfiguration and in component you can check how data is sent – Kay Feb 15 '22 at 13:41

1 Answers1

0

Because INITIAL_VALUE infers the types of your defined values and thus can only be mapped directly with names of properties (basically keys of your INITIAL_VALUE) and not string types. You can define a type for your initialState

interface InitialState {
  recipes: Recipe[],
  likedRecipes: {
    recipes: Recipe[],
    totalAmount: number,
  },
  recipeTypes: string[], // you could define your own literal types/intersection of literal types here
                        // made it as strings just for shorter explanation
  recipeTime: string[], // here as well
  recipeTitle: string,
  filterTypes: string[],
  filterLengths: string[],
}

And then you need to make your filterName prop to be keyof InitialState

type FilteringConfiguration = {
  content: string;
  type: typeOfFiltering;
  set: boolean;
  filterName: keyof InitialState; // <--
};

Or the other option is to type filterName as keyof typeofINITIAL_VALUE if you don't want to extract your type to a separate type definition and want to leave it as you have.

...
filterName: keyof typeof INITIAL_VALUE
...

Typescript Playground link
Redux toolkit has Usage with Typescript docs which might help you in future.

Mod3rnx
  • 828
  • 1
  • 10
  • 21
  • But I get next error Property 'push' does not exist on type 'string | string[] | WritableDraft[] | WritableDraft<{ recipes: Recipe[]; totalAmount: number; }>'. Property 'push' does not exist on type 'string'. addFilters(state, action: PayloadAction) { state[action.payload.nameOfFilter].push(action.payload.content); }, – Kay Feb 16 '22 at 09:10
  • Could you please update your code in question? – Mod3rnx Feb 16 '22 at 09:18
  • Post was updated sir – Kay Feb 16 '22 at 09:56
  • Have you typed ```INITIAL_VALUE``` to be ```InitialState``` shape? Because you either do that and make filterName ```keyof``` of that type, or you either don't do that and make it ```keyof typeof INITIAL_VALUE```, i can't reproduce your error, might be a type mismatch somewhere. – Mod3rnx Feb 16 '22 at 10:07
  • I updated INITIAL_VALUE, yeah it is InitialState shape. – Kay Feb 16 '22 at 10:12
  • I have no idea how to overcome this problem – Kay Feb 16 '22 at 10:54
  • Try removing type casting ```[] as Recipe[]``` because you don't need them anymore, since you have all your types in ```InitialState``` type now. – Mod3rnx Feb 16 '22 at 11:14
  • I deleted type casting the problem is that key is 'string | string[] | WritableDraft[] | WritableDraft<{ recipes: Recipe[]; totalAmount: number; }>'. It takes types of values, how to solve it then? – Kay Feb 16 '22 at 11:22
  • @Kay did you manage to find a solution after all? I'm struggling with the same problem – Lupexlol Jun 21 '22 at 21:10