Filtering object keys with typescript

Viewed 1075

Here is a sandbox showing the issue. https://codesandbox.io/s/trusting-moon-n058k?file=/src/index.ts

Input :

data.types = {
        starter: true,
        main: false,
        side: false,
        dessert: true,
        drink: false
    }

Desired output :

recipe.types = ["starter", "dessert"]

Solution :

type NewRecipeFormValues = {
    types: {
        starter: boolean,
        main: boolean,
        side: boolean,
        dessert: boolean,
        drink: boolean
    }
}

const postNewRecipe = (data: NewRecipeFormValues) => {
  let recipe = JSON.parse(JSON.stringify(data));
  recipe.types = Object.keys(data.types).filter(
    (key: keyof NewRecipeFormValues["types"]) => data.types[key]
  );
};

Problem : Typescript never shutups no matter what type I use.

Any help would be appreciated because I'm losing my mind

1 Answers

The error happens because the compiler cannot infer the runtime type of the key because Object.keys can return an arbitrary list of strings that are not necessarily keyof NewRecipeFormValues["types"] type.

Therefore, you need to explicitly tell the compiler that key is indeed keyof NewRecipeFormValues["types"] so that it can calm down.

To do that, use type assertion.

type NewRecipeFormValues = {
  types: {
    starter: boolean;
    main: boolean;
    side: boolean;
    dessert: boolean;
    drink: boolean;
  };
};

const postNewRecipe = (data: NewRecipeFormValues) => {
  let recipe = JSON.parse(JSON.stringify(data));
  recipe.types = Object.keys(data.types).filter(
    (key) => data.types[key as keyof NewRecipeFormValues["types"]]
  );
};

Check this playground.

As for why you cannot use key: keyof NewRecipeFormValues["types"] syntax, the linked documentation explains it better.

Related