TypeScript - پارامتر از نوع اتحادیهی انومها؟


آنچه من دارم دو شمارش هستند

enum Fruit { Apples, Oranges };
enum Vegetable { Garlic, Cucumber };

و یک نوع

type Food = Fruit | Vegetable;

حال میخواهم نوع دیگری بسازم که یک تابع باشد و یک غذا را به عنوان پارامتر دریافت کند

type OnViewFood = (food: Food) => void;

اما وقتی انجام میدهم

viewFruit: OnViewFood = (fruit: Fruit) => `This is ${fruit}`;

من یک خطا دریافت میکنم که Food قابل اختصاص دادن به Fruit نیست. چگونه میتوانم به هدفم برسم؟

پاسخ شماره ۱

دلیل اینکه کامپایلر نمیخواهد شما این کار را انجام دهید این است که اساساً ایمن نیست. تصور کنید اگر این مثال معتبر بود:

// 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);  

شما میتوانید OnViewFood را به عنوان یک اجتماع از توابع اعلام کنید، اما در این صورت فراخوانی آن مشکل میشود زیرا نمیتوانید یک اجتماع از توابع را فراخوانی کنید و همچنین نمیتوانید بهراحتی از محافظت نوع استفاده کنید:

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 

در هر دو صورت میتوانیم از تایپ اسرتیشن استفاده کنیم تا از خطای نوع عبور کنیم، و میتوانید به هر گزینهای بروید، بسته به اینکه بیشتر به کدام طرف اعتماد دارید، طرف ایجادکننده تابع یا طرف فراخواننده:

// 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);