Reputation: 51
What I have are two enums
enum Fruit { Apples, Oranges };
enum Vegetable { Garlic, Cucumber };
and a type
type Food = Fruit | Vegetable;
Now I want to make another type that is a function and takes a food as a parameter
type OnViewFood = (food: Food) => void;
But when I do
viewFruit: OnViewFood = (fruit: Fruit) => `This is ${fruit}`;
I get an error that Food is not assignable to Fruit. How do I achieve my goal?
Upvotes: 3
Views: 416
Reputation: 249556
The reason the compiler doesn't want you to do this is because it is essentially not safe. Consider if this example were valid:
// we assign a function that can only handle Fruit.
let viewFruit: OnViewFood = (fruit: Fruit) => `This is ${fruit}`;
// the declared signature allows us to use a Vegetable,
// possibly causing an error
viewFruit(Vegetable.Cucumber);
You can declare OnViewFood
to be a union of functions, but then calling becomes an issue since you can't call a union of functions and you can't easily type-guard :
type OnViewFood = ((food: Fruit) => void) | ((food: Vegetable) => void);
let viewFruit: OnViewFood = (fruit: Fruit) => `This is ${fruit}`;
// ok now can be either function signature
viewFruit(Vegetable.Cucumber); // now an error
In either case we can use a type assertion to get around the type error, and you can go for either option, depending on which side you trust more, the function creator side or the caller side:
// Type assertion on call
type OnViewFood = ((food: Fruit) => void) | ((food: Vegetable) => void);
let viewFruit: OnViewFood = (fruit: Fruit) => `This is ${fruit}`;
(viewFruit as any as ((food: Vegetable) => void))(Vegetable.Cucumber);
// Type assertion on declaration
type OnViewFood = (food: Food) => void
let viewFruit: OnViewFood = ((fruit: Fruit) => `This is ${fruit}`) as (food: Food) => void;
viewFruit(Vegetable.Cucumber);
Upvotes: 2