Extending HTML elements in React and TypeScript while preserving props

Josh picture Josh · Nov 22, 2016 · Viewed 54.8k times · Source

I just can't wrap my head around this I guess, I've tried probably half a dozen times and always resort to any... Is there a legitimate way to start with an HTML element, wrap that in a component, and wrap that in another component such that the HTML props pass through everything? Essentially customizing the HTML element? For example, something like:

interface MyButtonProps extends React.HTMLProps<HTMLButtonElement> {}
class MyButton extends React.Component<MyButtonProps, {}> {
    render() {
        return <button/>;
    }
} 

interface MyAwesomeButtonProps extends MyButtonProps {}
class MyAwesomeButton extends React.Component<MyAwesomeButtonProps, {}> {
    render() {
        return <MyButton/>;
    }
}

Usage:

<MyAwesomeButton onClick={...}/>

Whenever I attempt this sort of composition, I get an error similar to:

Property 'ref' of foo is not assignable to target property.

Answer

Jordan Upham picture Jordan Upham · Aug 14, 2017

You can change the definition of your component to allow the react html button props

class MyButton extends React.Component<MyButtonProps & React.HTMLProps<HTMLButtonElement>, {}> {
    render() {
        return <button {...this.props}/>;
    }
}

That will tell the typescript compiler that you want to enter the button props along with 'MyButtonProps'