@devdev10111

Как правильно объединить два типа HTMLElement?

Привет! Есть компонент, корнем которого может быть либо тег a, либо button. Это будет решаться в зависимости от наличия пропа href

const TappableComponent = (props: TappableComponentProps) => {
     const Component = props?.href ? 'a' : 'button';
     return <Component>...</Component>
}


Соответственно, нужно чтобы в пропсах можно было указать все аттрибуты от button и от a. Сделал так:
interface TappableComponentProps extends
  Partial<AnchorHTMLAttributes<HTMLAnchorElement>>,
  Partial<ButtonHTMLAttributes<HTMLButtonElement>> {
  size?: 's' | 'm' | 'l';
}

но ts ругается на большое количество не идентичных типов в AnchorHTMLAttributes и ButtonHTMLAttributes.

вручную вытягивать через
Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'href' | 'target' | etc>

кажется неверным методом, может есть решение получше?
  • Вопрос задан
  • 95 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
Ответ Александр хорошо работает если есть дискриминатор (в приведённом примере поле type).

Если же такого уникального поля нет, то конкретно для React можно сделать на перегрузках, условно:
type ExtraProps = {
  size?: 's' | 'm' | 'l';
}

type AnchorProps = ExtraProps & {href: string};
type ButtonProps = ExtraProps & {type: string};

function TappableComponent(props: AnchorProps ): ReactNode; 
function TappableComponent(props: ButtonProps ): ReactNode;
function TappableComponent(props: AnchorProps | ButtonProps ) {
     const Component = 'href' in props ? 'a' : 'button';
     return <Component>...</Component>
}

Там множество подводных камней, но иногда удобно.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы