英文:
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 "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>;
};
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<React.HTMLProps<HTMLElement>, "color" | "height" | "size" | "width" | "as">
Omit<React.HTMLProps<HTMLButtonElement>, "color" | "height" | "size" | "width" | "as">
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<IconButtonProps> = ({ icon, ...props }) => {
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论