Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TS2322 Error when extending Button, component property not found. What is the correct way to type?

I am migrating from MUI v3 to v4. I have some wrapped Button components that extend some styling and other properties on the regular Material UI Button component. Since upgrading to v4, I get type errors with this. I am utilizing react-router-dom as my routing library.

When passing the forwarded ref components as written in the updated Button example in the MUI v4 documentation (here: https://material-ui.com/components/buttons/#third-party-routing-library) I get a type error that component does not exist in the props type I've provided for my wrapped button.

I've tried various combinations of types from the Button component to see if something else might work but it seems that ButtonProps should cover it based on the OverrideProps type that ButtonProps is built from.

Here is my reproduction in code sandbox:

https://codesandbox.io/s/mui-button-type-issue-dihdd?from-embed

Note: It takes a minute for the type errors to show up while Code Sandbox chugs through the types.

enter image description here

like image 726
gunn4r Avatar asked May 24 '19 22:05

gunn4r


1 Answers

This is happening for two reasons:

  1. ExtendedButton contains a MUIButton (which has the component property), but ExtendedButton isn't a MUIButton itself (so it doesn't have the component property).
  2. The component property is defined on OverridableComponent, not OverrideProps.

You need to implement the component property and pass it along to MUIButton:

const Button: React.FC<Props & { component: React.ElementType }> = ({
  component,
  // ...
}) => (
  <MUIButton
    component={component}
    // ...
  >
    // ...
  </MUIButton>
)

For reference, here is where component is defined in MUI:

export interface OverridableComponent<M extends OverridableTypeMap> {
  <C extends React.ElementType>(props: { component: C } & OverrideProps<M, C>): JSX.Element;
  (props: DefaultComponentProps<M>): JSX.Element;
}
like image 175
Matthew Avatar answered Oct 05 '22 15:10

Matthew