自定义按钮使用styled-components TypeScript

huangapple go评论93阅读模式
英文:

Custom Button using styled components typescript

问题

我尝试创建一个自定义按钮组件,它接受一个名为 'icon' 的属性。我们正在使用 style-components 和 styled system 进行实用程序样式设置。在渲染组件时,我遇到了 TypeScript 的重载错误。请参考以下组件代码:

import React, { FC, ReactNode } from "react";
import styled from "styled-components";
import {
  layout,
  space,
  variant,
  fontSize,
  border,
  shadow,
  LayoutProps,
  SpaceProps,
  FontSizeProps,
  BorderProps,
  ShadowProps,
  flexbox,
  FlexboxProps,
  position,
  PositionProps,
} from "styled-system";

export interface IconButtonProps
  extends LayoutProps,
    SpaceProps,
    FontSizeProps,
    BorderProps,
    ShadowProps,
    FlexboxProps,
    PositionProps,
    Omit<React.HTMLProps<HTMLElement>, "color" | "height" | "size" | "width" | "as"> {
  children: any;
  variant: "primary" | "secondary";
  icon: ReactNode;
}

const IconButtonContainer = styled.button<IconButtonProps>`
  border-radius: ${({ theme }) => theme.space["spacing-200"]};
  display: inline-flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-size: ${({ theme }) => theme.fontSizes["font-24"]};
  padding: "8px";
  ${variant({
    variants: {
      primary: {
        color: "neutral.0",
        backgroundColor: "blue.400",
        border: "1px solid",
        borderColor: "blue.400",
        "&:hover": {
          border: "1px solid",
          borderColor: "blue.300",
          backgroundColor: "blue.300",
        },
        "&:not(:disabled):not(.disabled):active": {
          border: "1px solid",
          borderColor: "blue.500",
          backgroundColor: "blue.500",
        },
        "&:disabled": {
          opacity: ".6",
          color: "neutral.60",
          border: "1px solid",
          borderColor: "neutral.50",
          backgroundColor: "neutral.20",
          cursor: "default",
        },
      },
      secondary: {
        backgroundColor: "transparent",
        border: "0",
        "&:hover": {
          border: "1px solid",
          backgroundColor: "blue.50",
        },
        "&:not(:disabled):not(.disabled):active": {
          border: "1px solid",
          backgroundColor: "blue.50",
        },
        "&:disabled": {
          border: "0",
          opacity: ".6",
          cursor: "default",
        },
      },
    },
  })}
  ${variant({
    prop: "size",
    variants: {
      medium: {
        fontWeight: "semibold",
        height: "24px",
      },
    },
  })}

  ${space} ${fontSize} ${border} ${layout} ${shadow} ${flexbox} ${position};
`;

export const IconButton = (props: IconButtonProps) => {
  return <IconButtonContainer {...props}>{props.icon}</IconButtonContainer>;
};

错误信息如下:

没有匹配此调用的重载。
重载 1 of 2, '(props: { cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; } & { ...; } & { ...; }): ReactElement<...>', 提供了以下错误。
类型 '{ children: ReactNode; variant: "primary" | "secondary"; icon: ReactNode; width?: ResponsiveValue<Width<TLengthStyledSystem>, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; wrap?: string | undefined; }' 不能分配给类型 '{ cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; }'。
ref 属性的类型不兼容。
类型 'LegacyRef<HTMLElement> | undefined' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'。
类型 'string' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'。
重载 2 of 2, '(props: StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">): ReactElement<StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">, string | JSXElementConstructor<...>>', 提供了以下错误。
类型 '{ children: ReactNode; variant: "primary" | "secondary"; icon: ReactNode; width?: ResponsiveValue<Width<TLengthStyledSystem>, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; wrap?: string | undefined; }' 不能分配给类型 '{ cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; }'。
ref 属性的类型不兼容。
类型 'LegacyRef<HTMLElement> | undefined' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'。ts(2769)
const IconButtonContainer: StyledComponent<"button", any, IconButtonProps, never>;

有人可以帮忙吗?我对 TypeScript 还不太熟悉,它一直在报错。

英文:

Im trying to create a custom button component which accepts icon as a prop 'icon', we are using style-components and styled system for utility styling. While rendering the component, im getting a typescript overload error. Please refer the component code:

import React, { FC, ReactNode } from &quot;react&quot;;
import styled from &quot;styled-components&quot;;
import {
layout,
space,
variant,
fontSize,
border,
shadow,
LayoutProps,
SpaceProps,
FontSizeProps,
BorderProps,
ShadowProps,
flexbox,
FlexboxProps,
position,
PositionProps,
} from &quot;styled-system&quot;;
export interface IconButtonProps
extends LayoutProps,
SpaceProps,
FontSizeProps,
BorderProps,
ShadowProps,
FlexboxProps,
PositionProps,
Omit&lt;React.HTMLProps&lt;HTMLElement&gt;, &quot;color&quot; | &quot;height&quot; | &quot;size&quot; | &quot;width&quot; | &quot;as&quot;&gt; {
children: any;
variant: &quot;primary&quot; | &quot;secondary&quot;;
icon: ReactNode;
}
const IconButtonContainer = styled.button&lt;IconButtonProps&gt;`
border-radius: ${({ theme }) =&gt; theme.space[&quot;spacing-200&quot;]};
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: ${({ theme }) =&gt; theme.fontSizes[&quot;font-24&quot;]};
padding: &quot;8px&quot;;
${variant({
variants: {
primary: {
color: &quot;neutral.0&quot;,
backgroundColor: &quot;blue.400&quot;,
border: &quot;1px solid&quot;,
borderColor: &quot;blue.400&quot;,
&quot;&amp;:hover&quot;: {
border: &quot;1px solid&quot;,
borderColor: &quot;blue.300&quot;,
backgroundColor: &quot;blue.300&quot;,
},
&quot;&amp;:not(:disabled):not(.disabled):active&quot;: {
border: &quot;1px solid&quot;,
borderColor: &quot;blue.500&quot;,
backgroundColor: &quot;blue.500&quot;,
},
&quot;&amp;:disabled&quot;: {
opacity: &quot;.6&quot;,
color: &quot;neutral.60&quot;,
border: &quot;1px solid&quot;,
borderColor: &quot;neutral.50&quot;,
backgroundColor: &quot;neutral.20&quot;,
cursor: &quot;default&quot;,
},
},
secondary: {
backgroundColor: &quot;transparent&quot;,
border: &quot;0&quot;,
&quot;&amp;:hover&quot;: {
border: &quot;1px solid&quot;,
backgroundColor: &quot;blue.50&quot;,
},
&quot;&amp;:not(:disabled):not(.disabled):active&quot;: {
border: &quot;1px solid&quot;,
backgroundColor: &quot;blue.50&quot;,
},
&quot;&amp;:disabled&quot;: {
border: &quot;0&quot;,
opacity: &quot;.6&quot;,
cursor: &quot;default&quot;,
},
},
},
})}
${variant({
prop: &quot;size&quot;,
variants: {
medium: {
fontWeight: &quot;semibold&quot;,
height: &quot;24px&quot;,
},
},
})}
${space} ${fontSize} ${border} ${layout} ${shadow} ${flexbox} ${position};
`;
export const IconButton = (props: IconButtonProps) =&gt; {
return &lt;IconButtonContainer {...props}&gt;{props.icon}&lt;/IconButtonContainer&gt;;
};

自定义按钮使用styled-components TypeScript
And the error is :
>No overload matches this call.
Overload 1 of 2, '(props: { cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; } & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Type '{ children: ReactNode; variant: "primary" | "secondary"; icon: ReactNode; width?: ResponsiveValue<Width<TLengthStyledSystem>, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; wrap?: string | undefined; }' is not assignable to type '{ cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; }'.
Types of property 'ref' are incompatible.
Type 'LegacyRef<HTMLElement> | undefined' is not assignable to type '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'.
Type 'string' is not assignable to type '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'.
Overload 2 of 2, '(props: StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">): ReactElement<StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">, string | JSXElementConstructor<...>>', gave the following error.
Type '{ children: ReactNode; variant: "primary" | "secondary"; icon: ReactNode; width?: ResponsiveValue<Width<TLengthStyledSystem>, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; wrap?: string | undefined; }' is not assignable to type '{ cite?: string | undefined; data?: string | undefined; form?: string | undefined; label?: string | undefined; p?: ResponsiveValue<string | number | symbol, Required<Theme<TLengthStyledSystem>>> | undefined; ... 445 more ...; left?: ResponsiveValue<...> | undefined; }'.
Types of property 'ref' are incompatible.
Type 'LegacyRef<HTMLElement> | undefined' is not assignable to type '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'.ts(2769)
const IconButtonContainer: StyledComponent<"button", any, IconButtonProps, never>

Can someone please help, im a new to typescript and its throwing me more errors.

答案1

得分: 1

尝试更改这一行:

Omit<React.HTMLProps<HTMLElement>, "color" | "height" | "size" | "width" | "as">
Omit<React.HTMLProps<HTMLButtonElement>, "color" | "height" | "size" | "width" | "as">

如果这不起作用,你可能有一个问题,也许你需要指定 IconButton 的类型,因为它默认采用类型 "any"。

export const IconButton: FC<IconButtonProps> = ({ icon, ...props }) => {

如果你仍然遇到问题,也许最好创建一个新的类型来表示原生按钮的属性。

希望我的回答能帮助你。

英文:

Try change this line:

Omit&lt;React.HTMLProps&lt;HTMLElement&gt;, &quot;color&quot; | &quot;height&quot; | &quot;size&quot; | &quot;width&quot; | &quot;as&quot;&gt;
Omit&lt;React.HTMLProps&lt;HTMLButtonElement&gt;, &quot;color&quot; | &quot;height&quot; | &quot;size&quot; | &quot;width&quot; | &quot;as&quot;&gt;

If this doesn't work you might have a problem, maybe you ll need to specify type of IconButton, because it takes by default type any

export const IconButton: FC&lt;IconButtonProps&gt; = ({ icon, ...props }) =&gt; {

If you still got a problem maybe it's better to create a new type for the native button props.

Hope my answer will help you.

huangapple
  • 本文由 发表于 2023年7月12日 22:28:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76671669.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定