Specify specific props and accept general HTML props in Typescript React App Specify specific props and accept general HTML props in Typescript React App reactjs reactjs

Specify specific props and accept general HTML props in Typescript React App


We can have a look at how div props are defined:

interface IntrinsicElements {    div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;}

If we use React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> as the base type we will have all properties of div. Since DetailedHTMLProps just adds ref to React.HTMLAttributes<HTMLDivElement> we can use just this as the base interface to get all div properties:

interface WrapperProps extends React.HTMLAttributes<HTMLDivElement> {  callback?: Function}export class Wrapper extends React.Component<WrapperProps>{  render() {    const { callback, children, ...rest } = this.props;    return <div {...rest}>      {children}    </div>;  }}export const Test = () => {  return <Wrapper className="test">Hi there</Wrapper> // works now}


JSX.IntrinsicElements has this info, e.g.

const FooButton: React.FC<JSX.IntrinsicElements['button']> = props => (  <button {...props} className={`foo ${props.className}`} />)// alternative...const FooButton: React.FC<React.PropsWithoutRef<  JSX.IntrinsicElements['button']>> = props => <button {...props} className={`foo ${props.className}`} />

discovered this in the react-typescript-cheatsheet project.


A co-worker of mine figured it out. Sharing here for broader visibility:

interface ComponentPropTypes = {  elementName?: keyof JSX.IntrinsicElements; // list of all native DOM components  ...}// Function componentfunction Component({  elementName: Component = 'div',  ...rest,  // React.HTMLAttributes<HTMLOrSVGElement>) provides all possible native DOM attributes}: ComponentPropTypes & React.HTMLAttributes<HTMLOrSVGElement>)): JSX.Element {  return <Component {...rest} />;}// Class componentclass Component extends React.Component<ComponentPropTypes & React.HTMLAttributes<HTMLOrSVGElement>> {  render() {    const {      elementName: Component,      ...rest,    } = this.props;    return <Component {...rest} />  }}