简体   繁体   中英

How to generically type React component props and extend the generic props type

I have a component where the element type is parameterized. I'd like to type this component so you can specify the type of the element and constrain the props to that type.

interface IProps<T> extends T {
  elementName: string,
}

class Foo<T> extends React.Component<IProps<T>, {}> {
  render() {
    const { elementName, ...props } = this.props;
    return React.createElement(elementName, {
        ...props,
    });
  }
}

For example, href is a valid prop when the type of the props is AnchorHTMLAttributes but not when it's HTMLAttributes .

// Ok
<Foo<AnchorHTMLAttributes<AnchorHTMLElement>> href="foo.com"/>

// Type checker error because `href` is not an attribute of a div
<Foo<HTMLAttributes<HTMLDivElement>> href="foo.com"/>

Is this possible and if so, how?

Looks like type you want is:

React.InputHTMLAttributes<HTMLInputElement>

Swap out both Input 's for other types of tags.

And it looks like the most generic constraint would be:

React.HTMLAttributes<HTMLElement>

Then you can merge that type with something that gives you your elementName . With the constraint and the elementName you get:

function Foo<T extends React.HTMLAttributes<HTMLElement>>(
  props: T & { elementName: string },
) {
  const { elementName, ...otherProps } = props
  return React.createElement(elementName, otherProps)
}

Or as a class component:

class Foo<T extends React.HTMLAttributes<HTMLElement>> extends React.Component<
  T & { elementName: string }
> {
  render() {
    const { elementName, ...otherProps } = this.props
    return React.createElement(elementName, otherProps)
  }
}

Usage works like you seem to expect, though you will have to provide elementName .

function App() {
    return <>
        <Foo<React.InputHTMLAttributes<HTMLInputElement>>
          elementName="input"
          value={1}
        /> {/* valid */}

        <Foo<React.InputHTMLAttributes<HTMLInputElement>>
          elementName="input"
          href='/foo/bar'
        /> {/* Property 'href' does not exist on type */}
    </>
}

Working Playground

尝试使用这种类型,它扩展了 React.HTMLAttributes 并包含来自其他元素的 props:

React.AllHTMLAttributes<unknown>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM