I have a 'Food' object that can be of multiple types depending on the value of the 'category' prop. The object comes from a json, so it is impossible to know the type before.
I'm trying to use a switch statement on the category prop in order to cast the Food object to the right type
export type Category = 'fruit' | 'grain' | 'meat'
interface Food<IngredientCategory extends Category> {
name: string;
category: IngredientCategory
[key: string]: string;
}
interface Fruit extends Food<'fruit'> {
color: string;
}
interface Grain extends Food<'grain'>{
size: string;
}
interface Meat extends Food<'meat'> {
temperature: string
}
type FoodFromCategory<IngredientCategory extends Category> = IngredientCategory extends 'fruit' ? Fruit : IngredientCategory extends 'grain' ? Grain : Meat;
const castFood = <IngredientCategory extends Category>(category: IngredientCategory, food: Food<any>):
Food<IngredientCategory> | undefined => {
switch (category) {
case "fruit":
return food as Fruit
case "grain":
return food as Grain
case "meat":
return food as Meat
}
return undefined
};
This creates errors on the lines with the return:
TS2322: Type 'Fruit' is not assignable to type 'Food'. Types of property 'category' are incompatible. Type '"fruit"' is not assignable to type 'IngredientCategory'. '"fruit"' is assignable to the constraint of type 'IngredientCategory', but 'IngredientCategory' could be instantiated with a different subtype of constraint 'Category'.
Why doesn't the switch statement narrow down the "IngredientCategory" generic param? Is there another way I could do this?