Currently, my code looks something like this:
interface Apple {
type: 'Apple'
}
interface Banana {
type: 'Banana'
}
interface Coconut {
type: 'Coconut'
}
type Fruit = Apple | Banana | Coconut
type AppleOrBanana = Apple | Banana
const returnOnlyApplesOrBananas = (fruit: Fruit): Apple => {
if (fruit.type === 'Apple' || fruit.type === 'Banana') {
return fruit;
}
throw new Error('Unexpected type of fruit');
}
It typechecks successfully,
but the issue is that my actual 'Fruit' type is a much larger union.
I would really like to be able to do something like this:
const IdealReturnOnlyApplesOrBananas = (fruit: Fruit): Apple => {
if (AppleOrBanana['type'].includes(fruit.type)) {
return fruit;
}
throw new Error('Unexpected type of fruit');
}
It seems possible since the type checker knows what AppleOrBanana['type']
is because it's a type... I know how to define types based on constant arrays, so I'm wondering if the reverse is achievable.
If not, are there any smart techniques or patterns that could simplify my situation? Such as narrowing down a large union type to a smaller one safely.