我真的厌倦了搜索这个主题。我受不了……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属性传递给按钮类