将forwardRef与泛型一起使用时,我得到Property 'children' does not exist on type 'IntrinsicAttributes'
或Property 'ref' does not exist on type 'IntrinsicAttributes'
。
https://codesandbox.io/s/react-typescript-0dt6d?fontsize=14
上面CodeSandbox链接中的相关代码在此处复制:
interface SimpleProps<T extends string>
extends React.HTMLProps<HTMLButtonElement> {
random: T;
}
interface Props {
ref?: React.RefObject<HTMLButtonElement>;
children: React.ReactNode;
}
function WithGenericsButton<T extends string>() {
return React.forwardRef<HTMLButtonElement, Props & SimpleProps<T>>(
({ children, ...otherProps }, ref) => (
<button ref={ref} className="FancyButton" {...otherProps}>
{children}
</button>
)
);
}
() => (
<WithGenericsButton<string> ref={ref} color="green">
Click me! // Errors: Property 'children' does not exist on type 'IntrinsicAttributes'
</WithGenericsButton>
)
此处提出了一种可能的解决方案,但不确定如何在这种情况下实施: https://github.com/microsoft/TypeScript/pull/30215 (从https://stackoverflow.com/a/51898192/9973558找到)
答案 0 :(得分:2)
因此,这里的主要问题是您要在渲染器中返回React.forwardRef
的结果,这对于渲染函数来说不是有效的返回类型。您需要将forwardRef结果定义为它自己的组件,然后将其呈现在WithGenericsButton高阶组件中,如下所示:
import * as React from "react";
interface SimpleProps<T extends string> {
random: T;
}
interface Props {
children: React.ReactNode;
color: string;
}
function WithGenericsButton<T extends string>(
props: Props & SimpleProps<T> & { ref: React.Ref<HTMLButtonElement> }
) {
type CombinedProps = Props & SimpleProps<T>;
const Button = React.forwardRef<HTMLButtonElement, CombinedProps>(
({ children, ...otherProps }, ref) => (
<button ref={ref} className="FancyButton" {...otherProps}>
{children}
</button>
)
);
return <Button {...props} />;
}
const App: React.FC = () => {
const ref = React.useRef<HTMLButtonElement>(null);
return (
<WithGenericsButton<string> ref={ref} color="green" random="foo">
Click me!
</WithGenericsButton>
);
};
如果将其放在沙盒或游乐场中,您会看到props
的键入正确,其中包括random
的{{1}}道具
答案 1 :(得分:1)
您遇到的问题是由于此功能:
function WithGenericsButton<T extends string>() {
return React.forwardRef<HTMLButtonElement, Props & SimpleProps<T>>(
({ children, ...otherProps }, ref) => (
<button ref={ref} className="FancyButton" {...otherProps}>
{children}
</button>
)
);
}
WithGenericsButton
不是组件。这是一个返回组件的js函数。 TS基本上是在告诉您:嘿WithGenericsButton
组件(因为您将它作为一个组件使用)没有名为children
的道具,这是正确的,没有。
要获得可以渲染的组件,您需要执行以下操作:const StringButton = WithGenericsButton<string>();
答案 2 :(得分:1)
我找到了解决您问题的另一种好方法。像这样的东西
export interface Props = {
...yourPropsHere;
};
export interface CompoundedComponent extends React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLInputElement>> {
yourStaticFunctionOrSomethingLikeThat: () => void;
}
const Component = React.forwardRef<HTMLInputElement, Props>((props, ref) => (
<input ref={ref} {...props} />
)) as CompoundedComponent;
Component.yourStaticFunctionOrSomethingLikeThat = () => {};
答案 3 :(得分:0)
一个对我有用的方便的替代方法,(根本没有打字专家)
const ReusableComponent = React.forwardRef((props: { [key: string]: unknown }, ref) => {
const { ref, children, ...moreProps } = props
return (
<Something ref={ref} {...moreProps}>
{children}
</Something>
)
})
export default ReusableComponent
发现在无法知道您收到什么道具时使用 [key: string]: unknown
很方便。