I'm facing a problem with Typescript and React.
Let's supposed I have the following Union Type:
type Fruits = 'apple' | 'peach' | 'banana';
And I use it like this:
type FoodBaseProps = {
fruits: Fruits;
weight: number
price: number
}
Now, imagine that I have a boolean prop called needToPeel that should only be informed if the fruit banana is passed;
To solve that I did the following:
export type NeedToPeelFruitsProps = FoodBaseProps & {
fruits: Extract<Fruits, 'banana'>;
needToPeel?: boolean;
};
And for the other fruits that do not need to be peeled I have:
export type DefaultFruitsProps = FoodBaseProps & {
fruits: Exclude<Fruits, 'banana'>;
};
And then I have:
type FoodProps = NeedToPeelFruitsProps | DefaultFruitsProps;
Now, if I do some assertions based on this logic I'll have this (working as expected):
const testFn = (food: FoodProps) => {
switch (food.fruits) {
case 'banana': {
console.log(food.needToPeel); // No error
break;
}
case 'apple': {
console.log(food.needToPeel); // TS2339: Property 'needToPeel' does not exist on type 'DefaultFruitsProps'.
break;
}
default:
}
};
However, if I try to access this needToPeel prop in my React component, I'll have some problems:
const Food = ({
fruits,
weight,
price,
needToPeel, // TS2339: Property 'needToPeel' does not exist on type 'FoodProps'.
}: FoodProps) => {
return (
<FoodBase
fruits={fruits}
weight={weight}
price={price}
needToPeel={needToPeel} // 2 errors below
/>
)
}
1 - TS2769: No overload matches this call. Overload 1 of 2, '(props: Omit<Omit<Pick<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "key" | keyof HTMLAttributes<...>> & { ...; } & [...];
2 - TS2339: Property 'needToPeel' does not exist on type 'FoodProps'.
I think the problem is because union types only consider the props in common. So, needToPeel prop will not be accessible since it's not shared among the types.
I was wondering if there's a way to be able to access the needToPeel in my React component.