Я пытаюсь создать функцию, которая возвращает JSX в зависимости от свойства имени. Вот мой код:

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 выдает ошибку, потому что нельзя быть уверенным, что компоненты <Ionicons /> и <Feather /> содержат имя. Я попытался обойти это с помощью props.type, но TypeScript по-прежнему выдает ошибку. Как я могу вернуть правильный компонент без ошибки? Спасибо!

0
Ethan Keshishian 24 Мар 2021 в 04:19

1 ответ

Лучший ответ

Похоже, у Ionicons более 3000 имен, а у Feather их около 300. Что произойдет, если я вызову ваш компонент с помощью type="Feather" и имени, которое существует только на Ionicons?

Ваш компонент набран таким образом, что name является допустимой опорой, если она существует на либо Ionicons, либо Feather. Но этого недостаточно. Нам нужно знать, что значок существует в выбранном наборе значков .

Определение реквизита как объединения устранит ошибку.

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 />;
}
1
Linda Paiste 24 Мар 2021 в 23:10