自定义按钮使用styled-components TypeScript

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

Custom Button using styled components typescript

问题

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

  1. import React, { FC, ReactNode } from "react";
  2. import styled from "styled-components";
  3. import {
  4. layout,
  5. space,
  6. variant,
  7. fontSize,
  8. border,
  9. shadow,
  10. LayoutProps,
  11. SpaceProps,
  12. FontSizeProps,
  13. BorderProps,
  14. ShadowProps,
  15. flexbox,
  16. FlexboxProps,
  17. position,
  18. PositionProps,
  19. } from "styled-system";
  20. export interface IconButtonProps
  21. extends LayoutProps,
  22. SpaceProps,
  23. FontSizeProps,
  24. BorderProps,
  25. ShadowProps,
  26. FlexboxProps,
  27. PositionProps,
  28. Omit<React.HTMLProps<HTMLElement>, "color" | "height" | "size" | "width" | "as"> {
  29. children: any;
  30. variant: "primary" | "secondary";
  31. icon: ReactNode;
  32. }
  33. const IconButtonContainer = styled.button<IconButtonProps>`
  34. border-radius: ${({ theme }) => theme.space["spacing-200"]};
  35. display: inline-flex;
  36. justify-content: center;
  37. align-items: center;
  38. cursor: pointer;
  39. font-size: ${({ theme }) => theme.fontSizes["font-24"]};
  40. padding: "8px";
  41. ${variant({
  42. variants: {
  43. primary: {
  44. color: "neutral.0",
  45. backgroundColor: "blue.400",
  46. border: "1px solid",
  47. borderColor: "blue.400",
  48. "&:hover": {
  49. border: "1px solid",
  50. borderColor: "blue.300",
  51. backgroundColor: "blue.300",
  52. },
  53. "&:not(:disabled):not(.disabled):active": {
  54. border: "1px solid",
  55. borderColor: "blue.500",
  56. backgroundColor: "blue.500",
  57. },
  58. "&:disabled": {
  59. opacity: ".6",
  60. color: "neutral.60",
  61. border: "1px solid",
  62. borderColor: "neutral.50",
  63. backgroundColor: "neutral.20",
  64. cursor: "default",
  65. },
  66. },
  67. secondary: {
  68. backgroundColor: "transparent",
  69. border: "0",
  70. "&:hover": {
  71. border: "1px solid",
  72. backgroundColor: "blue.50",
  73. },
  74. "&:not(:disabled):not(.disabled):active": {
  75. border: "1px solid",
  76. backgroundColor: "blue.50",
  77. },
  78. "&:disabled": {
  79. border: "0",
  80. opacity: ".6",
  81. cursor: "default",
  82. },
  83. },
  84. },
  85. })}
  86. ${variant({
  87. prop: "size",
  88. variants: {
  89. medium: {
  90. fontWeight: "semibold",
  91. height: "24px",
  92. },
  93. },
  94. })}
  95. ${space} ${fontSize} ${border} ${layout} ${shadow} ${flexbox} ${position};
  96. `;
  97. export const IconButton = (props: IconButtonProps) => {
  98. return <IconButtonContainer {...props}>{props.icon}</IconButtonContainer>;
  99. };

错误信息如下:

  1. 没有匹配此调用的重载。
  2. 重载 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<...>', 提供了以下错误。
  3. 类型 '{ 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; }'
  4. ref 属性的类型不兼容。
  5. 类型 'LegacyRef<HTMLElement> | undefined' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'
  6. 类型 'string' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'
  7. 重载 2 of 2, '(props: StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">): ReactElement<StyledComponentPropsWithAs<"button", any, IconButtonProps, never, "button", "button">, string | JSXElementConstructor<...>>', 提供了以下错误。
  8. 类型 '{ 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; }'
  9. ref 属性的类型不兼容。
  10. 类型 'LegacyRef<HTMLElement> | undefined' 不能分配给类型 '((((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement>) & (string | ((instance: HTMLElement | null) => void) | RefObject<...>)) | null | undefined'ts(2769)
  11. 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:

  1. import React, { FC, ReactNode } from &quot;react&quot;;
  2. import styled from &quot;styled-components&quot;;
  3. import {
  4. layout,
  5. space,
  6. variant,
  7. fontSize,
  8. border,
  9. shadow,
  10. LayoutProps,
  11. SpaceProps,
  12. FontSizeProps,
  13. BorderProps,
  14. ShadowProps,
  15. flexbox,
  16. FlexboxProps,
  17. position,
  18. PositionProps,
  19. } from &quot;styled-system&quot;;
  20. export interface IconButtonProps
  21. extends LayoutProps,
  22. SpaceProps,
  23. FontSizeProps,
  24. BorderProps,
  25. ShadowProps,
  26. FlexboxProps,
  27. PositionProps,
  28. Omit&lt;React.HTMLProps&lt;HTMLElement&gt;, &quot;color&quot; | &quot;height&quot; | &quot;size&quot; | &quot;width&quot; | &quot;as&quot;&gt; {
  29. children: any;
  30. variant: &quot;primary&quot; | &quot;secondary&quot;;
  31. icon: ReactNode;
  32. }
  33. const IconButtonContainer = styled.button&lt;IconButtonProps&gt;`
  34. border-radius: ${({ theme }) =&gt; theme.space[&quot;spacing-200&quot;]};
  35. display: inline-flex;
  36. justify-content: center;
  37. align-items: center;
  38. cursor: pointer;
  39. font-size: ${({ theme }) =&gt; theme.fontSizes[&quot;font-24&quot;]};
  40. padding: &quot;8px&quot;;
  41. ${variant({
  42. variants: {
  43. primary: {
  44. color: &quot;neutral.0&quot;,
  45. backgroundColor: &quot;blue.400&quot;,
  46. border: &quot;1px solid&quot;,
  47. borderColor: &quot;blue.400&quot;,
  48. &quot;&amp;:hover&quot;: {
  49. border: &quot;1px solid&quot;,
  50. borderColor: &quot;blue.300&quot;,
  51. backgroundColor: &quot;blue.300&quot;,
  52. },
  53. &quot;&amp;:not(:disabled):not(.disabled):active&quot;: {
  54. border: &quot;1px solid&quot;,
  55. borderColor: &quot;blue.500&quot;,
  56. backgroundColor: &quot;blue.500&quot;,
  57. },
  58. &quot;&amp;:disabled&quot;: {
  59. opacity: &quot;.6&quot;,
  60. color: &quot;neutral.60&quot;,
  61. border: &quot;1px solid&quot;,
  62. borderColor: &quot;neutral.50&quot;,
  63. backgroundColor: &quot;neutral.20&quot;,
  64. cursor: &quot;default&quot;,
  65. },
  66. },
  67. secondary: {
  68. backgroundColor: &quot;transparent&quot;,
  69. border: &quot;0&quot;,
  70. &quot;&amp;:hover&quot;: {
  71. border: &quot;1px solid&quot;,
  72. backgroundColor: &quot;blue.50&quot;,
  73. },
  74. &quot;&amp;:not(:disabled):not(.disabled):active&quot;: {
  75. border: &quot;1px solid&quot;,
  76. backgroundColor: &quot;blue.50&quot;,
  77. },
  78. &quot;&amp;:disabled&quot;: {
  79. border: &quot;0&quot;,
  80. opacity: &quot;.6&quot;,
  81. cursor: &quot;default&quot;,
  82. },
  83. },
  84. },
  85. })}
  86. ${variant({
  87. prop: &quot;size&quot;,
  88. variants: {
  89. medium: {
  90. fontWeight: &quot;semibold&quot;,
  91. height: &quot;24px&quot;,
  92. },
  93. },
  94. })}
  95. ${space} ${fontSize} ${border} ${layout} ${shadow} ${flexbox} ${position};
  96. `;
  97. export const IconButton = (props: IconButtonProps) =&gt; {
  98. return &lt;IconButtonContainer {...props}&gt;{props.icon}&lt;/IconButtonContainer&gt;;
  99. };

自定义按钮使用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

尝试更改这一行:

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

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

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

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

希望我的回答能帮助你。

英文:

Try change this line:

  1. Omit&lt;React.HTMLProps&lt;HTMLElement&gt;, &quot;color&quot; | &quot;height&quot; | &quot;size&quot; | &quot;width&quot; | &quot;as&quot;&gt;
  1. 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

  1. 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:

确定