类型声明.rest prop在带有typescript的React功能组件中



我真的厌倦了搜索这个主题。我受不了……Rest prop在函数组件中使用typescript接口。

如何声明…Rest prop与typescript接口或其他。

这是我的简单代码的一个例子。

应用程序。

function App() {
const handleClick = (): void => {
console.log('Clicked!!!');
};
return (
<div>
<div>
<Button success rounded outline className="mb-5"> //(*className throws error says: ype '{ children: (string | Element)[]; success: true; rounded: true; outline: true; className: string; }' is not assignable to type 'IntrinsicAttributes & Props'.
Property 'className' does not exist on type 'IntrinsicAttributes & Props'.*)
<GoBell />
Click Here!!
</Button>
</div>
<div>
<Button danger outline>
<GoCloudDownload />
Buy Now!
</Button>
</div>
<div>
<Button warning>
<GoDatabase />
See Deal!
</Button>
</div>
<div>
<Button secondary outline>
Hide Ads!
</Button>
</div>
<div>
<Button primary rounded>
Something
</Button>
</div>
</div>
);
}
export default App;

按钮。

import { ReactNode } from 'react';
import className from 'classnames';
import PropTypes from 'prop-types';
interface Props {
children: ReactNode;
primary?: boolean;
secondary?: boolean;
success?: boolean;
warning?: boolean;
danger?: boolean;
outline?: boolean;
rounded?: boolean;
rest?: //What can I write here?
}
function Button({
children,
primary,
secondary,
success,
warning,
danger,
outline,
rounded,
...rest
}: Props) {
const classes = className(
rest.className, // ( *There is error says: Property 'className' does not exist on type '{ rest?: any; }'* )
'flex items-center px-3 py-1.5 border transition',
{
'border-blue-500 bg-blue-500 text-white hover:bg-blue-600': primary,
'border-gray-800 bg-gray-800 text-white hover:bg-gray-900': secondary,
'border-green-500 bg-green-500 text-white hover:bg-green-600': success,
'border-yellow-500 bg-yellow-500 text-white hover:bg-yellow-600': warning,
'border-red-500 bg-red-500 text-white hover:bg-red-600': danger,
'rounded-full': rounded,
'bg-white': outline,
'text-blue-500': outline && primary,
'text-gray-800': outline && secondary,
'text-green-500': outline && success,
'text-yellow-500': outline && warning,
'text-red-500': outline && danger,
}
);
if (
Number(!!primary) +
Number(!!secondary) +
Number(!!success) +
Number(!!warning) +
Number(!!danger) >
1
) {
return (
<button className={classes}>Please select only one variation!!!</button>
);
}
return (
<button className={classes} {...rest}>
{children}
</button>
);
}
export default Button;

我尝试了很多东西。这是我尝试过的一些修复;

inside Button.tsx

1)
interface Props {
.......
rest?: Array<any> 
}
2)
interface Props {
.......
rest?: [any] 
}
3)
interface Props {
.......
rest?: Array<{className: string}> 
}
etc..

你可以添加indexer属性,但正如Chris所说,这听起来真的是一个糟糕的主意:

interface Props {
children: ReactNode;
primary?: boolean;
secondary?: boolean;
success?: boolean;
warning?: boolean;
danger?: boolean;
outline?: boolean;
rounded?: boolean;
[p:keyof any]: any
}

为什么这么糟糕?

首先,TS类型是一个最小的契约,所以每个类型对象都可以有其类型指定的属性以外的属性,通常你可以在使用in操作符检查属性是否存在后使用它。

其次,这听起来像是为了添加一个小小的类名而放弃了许多TS特性。

有更好的方法,比如添加className (OK OK我明白,如果有大量的道具要添加,它可能会很棘手)。

或者更好,扩展Props类型:

import React from "react";

type Props = {
primary?: boolean;
} & Omit<JSX.IntrinsicElements["button"], "className" | "ref">;

const Button = React.forwardRef<HTMLButtonElement>(({
primary = false,
...rest
}: Props, ref) => {
return (
<button className={primary ? "primary" : ""} ref={ref} {... rest} />
);
});

export default Button;

& Omit<JSX.IntrinsicElements["button"], "className" | "ref">add to Props Type除"className" | "ref"JSX.IntrinsicElements["button"]的所有属性

primary = false,不确定组件内部是true | false,这听起来比true | false | undefined好。

React.forwardRef<HTMLButtonElement>((..., ref)将ref参数转发给其他元素,这允许调用者在需要时访问真正的html按钮。

JSX中的ref={ref} {... rest}将ref属性和所有rest属性传递给按钮类

相关内容

  • 没有找到相关文章

最新更新