Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Link] typescript error Property 'component' does not exist on type IntrinsicAttributes ... #16846

Closed
2 tasks done
linlycode opened this issue Aug 1, 2019 · 25 comments · Fixed by #16487
Closed
2 tasks done

Comments

@linlycode
Copy link

Link does not accept component property on some cases

  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

I've looked #14970 #15827 but didn't find the solution

Expected Behavior 🤔

<Link component={MyComponent} />

should compile with no error

Current Behavior 😯

In some cases(required props not supplied), typescript reports error Property 'component' does not exist on type IntrinsicAttributes & AnchorHTMLAttributes<HTMLAnchorElement> ...

Steps to Reproduce 🕹

Link: codesandbox

  1. Open demo.tsx
  2. Sees 3 compilation errors

Code:

import React, { ReactNode } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Link, { LinkProps } from "@material-ui/core/Link";
import { Link as RouterLink } from "react-navi";

const useStyles = makeStyles(theme => ({
  link: {
    marginRight: theme.spacing(1),
    cursor: "pointer"
  }
}));

interface Props {
  to: string;
  children: ReactNode;
}

function SimpleLink(props: Props) {
  const { to, children, ...restProps } = props;
  return (
    <a {...restProps} href={to}>
      {children}
    </a>
  );
}

function IconLink(props: LinkProps) {
  return (
    <Link {...props} component={RouterLink}>
      !SomeIcon
    </Link>
  );
}

export default function ButtonRouter() {
  const classes = useStyles();
  return (
    <>
      <Link className={classes.link}>Plain</Link>

      <Link className={classes.link} component={SimpleLink}>
        !Simple
      </Link>

      <Link
        className={classes.link}
        to="https://github.com"
        component={SimpleLink}
      >
        Simple
      </Link>

      <Link className={classes.link} component={RouterLink}>
        !Navi Router
      </Link>

      <Link
        className={classes.link}
        href="https://frontarm.com/navi"
        component={RouterLink}
      >
        Navi Router
      </Link>

      <IconLink />
    </>
  );
}

Context 🔦

Wrap Link component to provide custom tooltip, styles etc.

Your Environment 🌎

Tech Version
Material-UI ^4.2.1
React 16.8.6
Browser Chrome
TypeScript 3.5.3
@spaceexperiment
Copy link
Contributor

spaceexperiment commented Aug 2, 2019

I get the same error when i try to use component prop e.g.
<List component="nav"> or <ListItem component="div"

Type error: Type '{ children: Element[]; component: string; }' is not assignable to type 'IntrinsicAttributes & { dense?: boolean; disablePadding?: boolean; subheader?: ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)>; } & CommonProps<...> & Pick<...>'.
  Property 'component' does not exist on type 'IntrinsicAttributes & { dense?: boolean; disablePadding?: boolean; subheader?: ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)>; } & CommonProps<...> & Pick<...>'.  TS2322

@vtrphan
Copy link

vtrphan commented Aug 5, 2019

I also got this problem after upgrading to v4. TS complained that
Property 'component' does not exist on type 'IntrinsicAttributes & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefin ed; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.

@khryshyn
Copy link

khryshyn commented Aug 5, 2019

I've got the same issue. To solve it I've used the proposed solution from Mui documentation
https://material-ui.com/components/buttons/#third-party-routing-library

const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

But the solution is not working if you're using the styled-components

@mrm-rideos
Copy link

One thing I noticed that may help folks who are encountering this: in my case, I got this error when passing a property to the Link/Button component that was not valid for the component in the component property. For example:

const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

<Button color="primary" component={AdapterLink} to="/" badProp>
  Simple case
</Button>

would give the same error about a non-existent component property.

This is a very misleading error from TypeScript, as the issue is the badProp property, not the component property, but the error message complains about the component property.

@mrm-rideos
Copy link

However, in addition to the above error (which went away when I removed the offending property), I also always get this error when trying to override the component property in the theme (props.MuiLink.component). I couldn't find any workaround or fix for this.

@trainbolt
Copy link

What is the status of this??? It does not seem like there's a fix for this or some solution that helps us solve the issue.

Custom Button

import { Button, createStyles, withStyles, WithStyles } from "@material-ui/core";
import { ButtonProps } from "@material-ui/core/Button";
import React from "react";
import { Link as RouterLink, LinkProps as RouterLinkProps } from "react-router-dom";
import Colors, { rgba } from "theme/colors";

const styles = () =>
  createStyles({
    root: {
      color: rgba(Colors.white, 0.5),
      backgroundColor: rgba(Colors.white, 0.05),
      "&:hover": {
        color: rgba(Colors.white, 0.75),
        backgroundColor: rgba(Colors.white, 0.2)
      }
    }
  });

const LinkRef = React.forwardRef<HTMLAnchorElement, RouterLinkProps>((props, ref) => (
  <RouterLink innerRef={ref} {...props} />
));

class CustomButton extends React.Component<ButtonProps & WithStyles> {
  public render() {
    return <Button component={LinkRef} {...this.props} />;
  }
}

export default withStyles(styles)(LoginSignupButton);

Usage

<CustomButton to="/register" component={Link}>Button Text</CustomButton>

Error

No overload matches this call.
  Overload 1 of 3, '(props: { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' is not assignable to type 'IntrinsicAttributes & { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<...> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps...'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<...> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps...'.
  Overload 2 of 3, '(props: { component: ForwardRefExoticComponent<LinkProps<any> & RefAttributes<HTMLAnchorElement>>; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; ... 8 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Property 'to' is missing in type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' but required in type 'Pick<LinkProps<any> & RefAttributes<HTMLAnchorElement>, "ref" | "component" | "to" | "replace" | "download" | "href" | "hrefLang" | "media" | "ping" | "rel" | "target" | "type" | ... 252 more ... | "key">'.
  Overload 3 of 3, '(props: DefaultComponentProps<ExtendButtonBaseTypeMap<ExtendButtonBaseTypeMap<{ props: { color?: "inherit" | "primary" | "secondary" | "default" | undefined; disableFocusRipple?: boolean | undefined; endIcon?: ReactNode; fullWidth?: boolean | undefined; href?: string | undefined; size?: "small" | ... 2 more ... | undefined; startIcon?: ReactNode; variant?: "text" | ... 2 more ... | undefined; }; defaultComponent: "button"; classKey: ButtonClassKey; }>>>): Element', gave the following error.
    Type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' is not assignable to type 'IntrinsicAttributes & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>'. 

@trainbolt
Copy link

trainbolt commented Oct 20, 2019

Not to mention...

const LinkRef = React.forwardRef<HTMLAnchorElement...
               ^^^^^^

Component definition is missing display name

@tsturtz
Copy link

tsturtz commented Dec 12, 2019

What is the status of this??? It does not seem like there's a fix for this or some solution that helps us solve the issue.

Custom Button

import { Button, createStyles, withStyles, WithStyles } from "@material-ui/core";
import { ButtonProps } from "@material-ui/core/Button";
import React from "react";
import { Link as RouterLink, LinkProps as RouterLinkProps } from "react-router-dom";
import Colors, { rgba } from "theme/colors";

const styles = () =>
  createStyles({
    root: {
      color: rgba(Colors.white, 0.5),
      backgroundColor: rgba(Colors.white, 0.05),
      "&:hover": {
        color: rgba(Colors.white, 0.75),
        backgroundColor: rgba(Colors.white, 0.2)
      }
    }
  });

const LinkRef = React.forwardRef<HTMLAnchorElement, RouterLinkProps>((props, ref) => (
  <RouterLink innerRef={ref} {...props} />
));

class CustomButton extends React.Component<ButtonProps & WithStyles> {
  public render() {
    return <Button component={LinkRef} {...this.props} />;
  }
}

export default withStyles(styles)(LoginSignupButton);

Usage

<CustomButton to="/register" component={Link}>Button Text</CustomButton>

Error

No overload matches this call.
  Overload 1 of 3, '(props: { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' is not assignable to type 'IntrinsicAttributes & { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<...> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps...'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { href: string; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<...> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps...'.
  Overload 2 of 3, '(props: { component: ForwardRefExoticComponent<LinkProps<any> & RefAttributes<HTMLAnchorElement>>; } & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; ... 8 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Property 'to' is missing in type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' but required in type 'Pick<LinkProps<any> & RefAttributes<HTMLAnchorElement>, "ref" | "component" | "to" | "replace" | "download" | "href" | "hrefLang" | "media" | "ping" | "rel" | "target" | "type" | ... 252 more ... | "key">'.
  Overload 3 of 3, '(props: DefaultComponentProps<ExtendButtonBaseTypeMap<ExtendButtonBaseTypeMap<{ props: { color?: "inherit" | "primary" | "secondary" | "default" | undefined; disableFocusRipple?: boolean | undefined; endIcon?: ReactNode; fullWidth?: boolean | undefined; href?: string | undefined; size?: "small" | ... 2 more ... | undefined; startIcon?: ReactNode; variant?: "text" | ... 2 more ... | undefined; }; defaultComponent: "button"; classKey: ButtonClassKey; }>>>): Element', gave the following error.
    Type '{ action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 282 more ...; component: ForwardRefExoticComponent<...>; }' is not assignable to type 'IntrinsicAttributes & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { action?: ((instance: ButtonBaseActions | null) => void) | RefObject<ButtonBaseActions> | null | undefined; buttonRef?: ((instance: unknown) => void) | RefObject<unknown> | null | undefined; ... 7 more ...; TouchRippleProps?: Partial<...> | undefined; } & { ...; } & CommonProps<...> & Pick<...>'. 

Btw, I had this same exact error on an <IconButton /> but it was another prop (onMouseUp) that had an incorrect type. Just make sure to check other props. It showed me the correct error after I added component="button".

@5t33

This comment has been minimized.

@danawoodman
Copy link

danawoodman commented Feb 17, 2020

This is indeed still an issue from what I can tell using the latest MUI, React and Typescript I get these errors for custom components as well as the default options:

<Button component="a">This fails</Button>

AFAIK this should be re-opened.

EDIT: This is strange, it is now working after I did a completely unrelated thing (increase VSCode's Typescript memory allotment). As far as I can tell, I changed nothing else to get the error to go away 🤷‍♂

@pashamesh
Copy link

@tsturtz please check if @types/react-router-dom is installed.

@nosovsh
Copy link

nosovsh commented Jan 25, 2021

Typescript errors are VERY misleading here. Please check that you provide only correct props.

E.g. in my case I had a Button that supposed to be link or action button depending on to prop. I tried this <Button onClick={onClick} component={to ? Link : undefined} to={to}> but that gave me an error Property 'component' does not exist on type 'IntrinsicAttributes... although the code was correct.

So I changed it to this and now there are no TS errors:

import { Link } from 'react-router-dom';

...

onClick?: MouseEventHandler<T>;
to?: string;

...

return to ? (
    <Button component={Link} to={to}>
      {children}
    </MUIButton>
  ) : (
    <Button onClick={onClick}>{children}</Button>
  );

or like this:

  const props = {
    to,
    component: to ? Link : undefined,
    onClick: to ? undefined : onClick,
  };
  return <Button {...props}>{children}</Button>;

@Mustang95
Copy link

the component called in parent:

<Button selected={books.objectId}>

the component implemented:

function Button(props: { selected: string })

this works fine

@Dchole
Copy link

Dchole commented Jul 2, 2021

import { Button } from "@material-ui/core"
import { ButtonProps } from "@material-ui/core/Button"
import Link, { LinkProps } from "./Link"
import { forwardRef } from "react"

export type ButtonLinkProps = Omit<ButtonProps, "href"> &
  Pick<LinkProps, "href" | "as" | "prefetch">

const ButtonLink = forwardRef<ButtonLinkProps, any>((props, ref) => (
  <Button
    component={Link}
    ref={ref}
    {...props}
    role={undefined} // remove the button role
  />
))

ButtonLink.displayName = "ButtonLink"

export default ButtonLink

The code from the ./link file comes from the material-nextjs example

Using the custom button

import ButtonLink from "@/components/ButtonLink"

<ButtonLink
  href="/store"
  variant="contained"
  color="primary"
  endIcon={<StoreIcon />}
>
  Go to our store
</ButtonLink>

This worked for me

@konrazem
Copy link

What I did I reinstalled the material-ui package and for version 4.12.2 problem disappeared.

@bristoljon
Copy link

Anyone else think the best solution might be just to not use Typescript?!

@rolmz
Copy link

rolmz commented Nov 16, 2021

Hi guys,

I had the same problem trying to add the nav option to a List component:

<List component='nav' style={{flex: 1, overflow: 'auto'}}>

to solve it, I just added the nav option as any variable:

<List component={'nav' as any} style={{flex: 1, overflow: 'auto'}}>

Is not a fancy solution, but works for me

@AngeliPeter
Copy link

For me, the problem was that I was using react-router-dom v6 which had some important breaking changes compared to previous versions (element instead of component, Routes instead of Switch etc). This stack overflow link helped a lot: https://stackoverflow.com/a/69849271

@matleve98
Copy link

I had the same issue, and the problem for me was also a problem in another prop. Interestingly it was enough to generate this kind of error message to use a badly typed value in the to prop. The solution was to update the to props path to a correct type (string, but the main point is that even a mistake like this can cause this kind of error message).



interface MenuTabs {
    path: unknown;
    title: string;
    icon: string;
    badgeContent?: number;
}

interface MenuItemsGroupProps {
    items: MenuTabs[];
}

type StyleProps = WithStyles<typeof styles>;

type Props = MenuItemsGroupProps & StyleProps;

const MenuItemsGroup: FC<Props> = ({ items, classes: { listItem } }) => (
    <>
        {items.map((item) => (
            <ListItem
                button
                classes={{ root: listItem }}
                component={Link}
                to={item.path}
                key={item.title}
            >
                <ListItemIcon>
                    <Img src={item.icon} />
                </ListItemIcon>
                <ListItemText primary={item.title} />
            </ListItem>
        ))}
    </>
);

export default withStyles(styles)(MenuItemsGroup);

@ayopunch
Copy link

ayopunch commented May 13, 2022

Mine was trying to forward a prop to a styled component using typescript. Was able to sort it out like this. I decided to set the props to a type of any and then destructure the props. Don't know if there is a better way to extend the type definition for a styled component.
`const Layout: FC = (): ReactElement => {
const props = {
open: open,
};
return (


<ContentWrapper {...props}>





);
};

const ContentWrapper = styled('main', {
shouldForwardProp: (props) => props !== 'open',
})((props: any) => {
const { theme, open } = props;
return {
width: calc(100% - ${theme.custom.sidebar.open}),
padding: theme.custom.pxToRem(16, open ? 16 : 40),
[theme.breakpoints.up('lg')]: {
padding: theme.custom.pxToRem(16, open ? 50 : 100),
},
};
});`

@abstractionslimited
Copy link

Hi All, the following solution worked for me:

import { Button, Link } from '@material-ui/core';
import React from 'react';

const ButtonLink = () => {
  return (
    <div>
      <Button variant='outlined' color='primary'>
        <Link href='/cart' underline='none'>
          Back to Cart
        </Link>
      </Button>
    </div>
  );
};

export default ButtonLink;

@abstractionslimited
Copy link

Hi All, the following solution worked for me:

import { Button, Link } from '@material-ui/core';
import React from 'react';

const ButtonLink = () => {
  return (
    <div>
      <Button variant='outlined' color='primary'>
        <Link href='/cart' underline='none'>
          Back to Cart
        </Link>
      </Button>
    </div>
  );
};

export default ButtonLink;

Or you can use Link from react-router-dom

import { Link } from 'react-router-dom';
 <Button component={Link}  to='/cart'  variant='outlined' color='primary'>
              Back to Cart
 </Button>

@gandhirahul
Copy link

With the latest mui v5, it's now fixed to use component prop with typescript.
To be able to use the component prop, the type of the props should be used with type arguments. Otherwise, the component prop will not be present.
(The same will work for any component which has props defined with OverrideProps)

import { ButtonProps } from '@mui/material/Button';

function CustomButton(props: ButtonProps<'a', { component: 'a' }>) {
  /* ... */
}
// ...
<CustomButton component="a" />;

If you need to use another component value, you can typecast it as below or update the above types.

<CustomButton
    variant="text"
    component={"div" as any}
/>

@vlod
Copy link

vlod commented Jun 22, 2023

This SO answer worked for me: https://stackoverflow.com/a/76300530

My code:

  interface IListItemButtonStyled {
    component: typeof NavLink;
    to: string;
  }

  const ListItemButtonStyled = styled(ListItemButton)<IListItemButtonStyled>(
    ({ theme }) => ({
      "&.active": {
        color: "#fff",
        backgroundColor: theme.palette.primary.light,

        "&:hover": {
          backgroundColor: theme.palette.primary.main,
        },
      },
    })
  );

<ListItem key="inbox" disablePadding>
            <ListItemButtonStyled component={NavLink} to="/dashboard/inbox">
              <ListItemIcon>
                <DraftsIcon />
              </ListItemIcon>
              <ListItemText primary="Inbox" />
            </ListItemButtonStyled>
          </ListItem>

@eleanorlatus
Copy link

Similar to gandhirahul's answer, this is what worked for me:

import { IconButton } from '@mui/material';

type MenuIconButtonProps = {
  component: string;
};

export const MenuIconButton = styled(IconButton)<MenuIconButtonProps>(() => ({
  display: 'flex',
  justifyContent: 'flex-start',
  alignItems: 'center',
}));

And then in my component I could render:

<MenuIconButton component="li" color="inherit"> 
...
</MenuIconButton>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.