Reputation: 83
I'm trying to create a function that returns JSX depending on the name prop. Here's my code:
function TabBarIcon(props: {
name:
| React.ComponentProps<typeof Ionicons>['name'] // 'key' | 'item' | 2000 more...
| React.ComponentProps<typeof Feather>['name']; // 2000 different strings...
color: string;
type: 'Ionicons' | 'Feather';
}) {
if (props.type === 'Ionicons')
return <Ionicons size={30} style={{ marginBottom: -3 }} {...props} />;
else if (props.type === 'Feather')
return <Feather size={30} style={{ marginBottom: -3 }} {...props} />;
else return <View />;
}
TypeScript throws an error because it can't be sure the <Ionicons />
and <Feather />
components contain name. I've attempted to workaround this with props.type, but TypeScript still throws an error. How can I return the correct component without the error? Thanks!
Upvotes: 0
Views: 768
Reputation: 42188
It looks like Ionicons
has over 3,000 names while Feather
has more like 300. What happens if I call your component with type="Feather"
and a name that only exists on Ionicons
?
Your component is typed such that a name
is a valid prop if it exists on either Ionicons
or Feather
. But that's not good enough. We need to know that the icon exists on the chosen icon set.
Defining the props as a union will make the error go away.
function TabBarIcon(props: {
color: string;
} & (
{
name: React.ComponentProps<typeof Ionicons>['name'];
type: 'Ionicons';
} | {
name: React.ComponentProps<typeof Feather>['name'];
type: 'Feather';
})) {
if (props.type === 'Ionicons')
return <Ionicons size={30} style={{ marginBottom: -3 }} {...props} />;
else if (props.type === 'Feather')
return <Feather size={30} style={{ marginBottom: -3 }} {...props} />;
else return <View />;
}
Upvotes: 2