【问题标题】:Adding variant to a Material-UI button with a custom component gives typescript errors使用自定义组件向 Material-UI 按钮添加变体会导致打字稿错误
【发布时间】:2021-05-22 04:46:38
【问题描述】:

我基于this example 制作了一个自定义链接组件。代码如下:

import classNames from 'classnames';
import {forwardRef} from 'react';
import MuiLink, {LinkProps as MuiLinkProps} from '@material-ui/core/Link';
import NextLink, {LinkProps as NextLinkProps} from 'next/link';
import isString from 'lodash/isString';
import {useRouter} from 'next/router';

import assert from '@todo/lib/assert';

type SelectedNextLinkProps = Pick<NextLinkProps, 'as' | 'href'>;
type SelectedMuiLinkProps = Omit<MuiLinkProps, 'href'>;

type ComposedLinkProps = Omit<SelectedMuiLinkProps, 'className'> & SelectedNextLinkProps;

const ComposedLink = forwardRef<HTMLAnchorElement, ComposedLinkProps>((props, ref): JSX.Element => {
  const {as, href, ...other} = props;
  return (
    <NextLink as={as} href={href}>
      <a ref={ref} {...other} />
    </NextLink>
  );
});
ComposedLink.displayName = 'ComposedLink';

type LinkProps = SelectedMuiLinkProps & SelectedNextLinkProps & {activeClassName?: string};

const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref): JSX.Element => {
  const {activeClassName: _, className, href, underline = 'none', ...other} = props;
  let {activeClassName} = props;

  const router = useRouter();

  const pathname = isString(href) ? href : href.pathname;
  assert(isString(pathname), 'Link requires a valid href');
  if (pathname !== router.pathname) {
    activeClassName = undefined;
  }

  return (
    <MuiLink
      className={classNames(className, activeClassName)}
      component={ComposedLink}
      href={pathname}
      ref={ref}
      underline={underline}
      {...other}
    />
  );
});
Link.displayName = 'Link';

export default Link;

我可以像这样在按钮中使用它:

<Button color="secondary" component={Link} href="/signup">
  Sign up
</Button>

但是当我添加一个变体道具时:

<Button color="secondary" component={Link} href="/signup" variant="contained">
  Sign up
</Button>

我收到难以理解的打字稿错误:

Type error: No overload matches this call.
  Overload 1 of 3, '(props: { href: string; } & { children?: ReactNode; color?: Color | undefined; disabled?: boolean | undefined; disableElevation?: boolean | undefined; disableFocusRipple?: boolean | undefined; ... 5 more ...; variant?: "text" | ... 2 more ... | undefined; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Type '{ children: string; component: ForwardRefExoticComponent<Pick<LinkProps, "color" | "display" | "translate" | "hidden" | "style" | "underline" | "as" | "href" | "className" | "classes" | "innerRef" | ... 265 more ... | "activeClassName"> & RefAttributes<...>>; href: string; color: "secondary"; variant: "contained"; }' is not assignable to type 'IntrinsicAttributes & { href: string; } & { children?: ReactNode; color?: Color | undefined; disabled?: boolean | undefined; disableElevation?: boolean | undefined; ... 6 more ...; variant?: "text" | ... 2 more ... | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { href: string; } & { children?: ReactNode; color?: Color | undefined; disabled?: boolean | undefined; disableElevation?: boolean | undefined; ... 6 more ...; variant?: "text" | ... 2 more ... | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.
  Overload 2 of 3, '(props: { component: ForwardRefExoticComponent<Pick<LinkProps, "color" | "display" | "translate" | "hidden" | "style" | "underline" | "as" | "href" | "className" | "classes" | "innerRef" | "slot" | ... 264 more ... | "activeClassName"> & RefAttributes<...>>; } & { ...; } & { ...; } & CommonProps<...> & Pick<...>): Element', gave the following error.
    Type 'string' is not assignable to type 'undefined'.
  Overload 3 of 3, '(props: DefaultComponentProps<ExtendButtonBaseTypeMap<ButtonTypeMap<{}, "button">>>): Element', gave the following error.
    Type '{ children: string; component: ForwardRefExoticComponent<Pick<LinkProps, "color" | "display" | "translate" | "hidden" | "style" | "underline" | "as" | "href" | "className" | "classes" | "innerRef" | ... 265 more ... | "activeClassName"> & RefAttributes<...>>; href: string; color: "secondary"; variant: "contained"; }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; color?: Color | undefined; disabled?: boolean | undefined; disableElevation?: boolean | undefined; ... 6 more ...; variant?: "text" | ... 2 more ... | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.
      Property 'component' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; color?: Color | undefined; disabled?: boolean | undefined; disableElevation?: boolean | undefined; ... 6 more ...; variant?: "text" | ... 2 more ... | undefined; } & { ...; } & CommonProps<...> & Pick<...>'.

  12 |       Sign in
  13 |     </Button>
> 14 |     <Button component={Link} href="/signup" color="secondary" variant="contained">
     |     ^
  15 |       Sign up
  16 |     </Button>
  17 |   </ButtonGroup>

我最好的猜测是该变体正在传递给我的自定义链接组件(在通往内部锚点的路上?我不知道),因为它不在道具中,所以打字稿爆炸了。谁能告诉我这里发生了什么?我该如何解决?

我在发布后注意到的另一件有趣的事情:tsc 错误,但我正在使用 babel 进行实际构建,babel 成功编译它并且它可以工作。所以,这似乎只是一个打字问题。

【问题讨论】:

    标签: reactjs typescript material-ui typescript-typings


    【解决方案1】:

    这个问题进入material-ui的兔子洞,所以如果你不感兴趣或者看不懂也没关系。

    在material ui中,Buttonbase默认是Button组件的根组件。 您已将其覆盖为自定义组件 Link,其类型(与 ButtonBase 不同)不允许“variant”作为其属性。

    这就是出现类型问题的原因。

    解决方案?让 Link 组件接受变体作为道具。也许将它添加到 LinkProps。这是你的选择

    来源 https://material-ui.com/guides/api/#spread https://material-ui.com/api/button/

    【讨论】:

    • 我尝试向 LinkProps 和 ComposedLinkProps 添加变体,但仍然遇到同样的错误。
    • @btmorex 你是怎么做到的?您将变体添加为类型字符串?我认为应该更具体
    • 我是这样添加的type LinkProps = SelectedMuiLinkProps &amp; SelectedNextLinkProps &amp; {activeClassName?: string; variant?: 'text' | 'outlined' | 'contained'};
    【解决方案2】:

    经过更多谷歌搜索,这似乎只是 Material-UI 中的一个错误,不会被反向移植到 4.x:https://github.com/mui-org/material-ui/issues/22452 如果有解决方法,我会接受。

    【讨论】:

      猜你喜欢
      • 2020-03-13
      • 2019-06-27
      • 2019-09-05
      • 2018-06-23
      • 2021-11-08
      • 1970-01-01
      • 2022-01-06
      • 2019-10-17
      • 1970-01-01
      相关资源
      最近更新 更多