Ruturaj Gole
Ruturaj Gole

Reputation: 51

Parameter of union type of enums?

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

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

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

Related Questions