React + Typescript: динамический класс на основе Prop

У меня есть компонент, в котором я передаю опору под названием HtmlTag, и, исходя из ее значения, я хотел бы расширить интерфейс опоры с помощью правильной базы реквизитов на теге html.

Я пробовал создать тип, который действует как карта, а затем попытался расширить его, например.

type AllAttrs = {
  a: AnchorHTMLAttributes,
  button: ButtonHTMLAttributes
}

и пробовать на данный момент следующее

interface Props extends AllAttrs["a"] {
  sanitize?: string;
}

и я получаю "интерфейс может расширять только другие интерфейсы"

Вот как я использую свой компонент:

<Element
   Component="a"
   ... more props
>Test</Element>

Цель состоит в том, чтобы TS жаловался на отсутствующие реквизиты, такие как href, если он не прошел.


person Giuliano    schedule 07.06.2019    source источник


Ответы (1)


У вас может быть интерфейс, расширяющий запрос индексированного типа, но вам нужно поместить его в псевдоним отдельного типа (он не может быть непосредственно в предложении extends).

Однако здесь это неправильный подход. Использование типа пересечения в реквизитах позволит логическому выводу работать должным образом (см. здесь):

type AllAttrs = {
  a: AnchorHTMLAttributes<HTMLAnchorElement>,
  button: ButtonHTMLAttributes<HTMLButtonElement>
}


function Element<T extends keyof AllAttrs>({ Component, ...rest}: { Component: T} & AllAttrs[T]){
  return <Component {...rest as any} ></Component>
}

let r = <Element
  Component="a"
  href=""
>Test</Element>

//Error href not on button
let r2 = <Element 
  Component="button"
  href=""
>Test</Element>
person Titian Cernicova-Dragomir    schedule 07.06.2019
comment
классно! работает очень хорошо. Я не знал, что могу использовать &, я пытался расширить и получал ошибку. - person Giuliano; 09.06.2019
comment
Единственное, что сейчас не работает, это опора children, когда я передаю ее, я получаю: Type 'string' is not assignable to type 'HTMLCollection | (HTMLCollection & string) | (HTMLCollection & number) | (HTMLCollection & false) | (HTMLCollection & true) | (HTMLCollection & ReactElement<any, string | ((props: any) => ReactElement<...>) | (new (props: any) => Component<...>)>) | (HTMLCollection & ReactNodeArray) | (HTMLCollection & ReactPortal)' - person Giuliano; 09.06.2019
comment
nvm, я предоставил неверный интерфейс для атрибута span, все хорошо, спасибо! - person Giuliano; 09.06.2019