如何解决带有更具体的 HTMLElement ref 的 Typescript/React ForwardRefExoticComponent 分配失败
我正在尝试编写一个 HOC 并输入您可以传递给它的子项。
场景看起来有点像这样(也在这个沙箱中:https://codesandbox.io/s/amazing-taussig-h2dpm?file=/src/App.tsx):
interface HOCProps {
modules: React.ForwardRefExoticComponent<
HOCChildProps & React.RefAttributes<HTMLElement>
>[];
}
interface HOCChildProps {
...
}
declare const HOC: React.FC<HOCProps>;
// this produces an error in HOCTest if HTMLDivElement is used
// and an error in HOCChildTest if HTMLElement is used
// as the ref type in React.forwardRef
const HOCChildTest = React.forwardRef<HTMLDivElement,HOCChildProps>(
(props,ref) => (
<div ref={ref}>
...
</div>
)
);
const HOCTest: React.FC = () => <HOC modules={[HOCChildTest]} />;
代码仍然有效,但输入无效。
看来这个任务失败了:
declare const divTest: React.ForwardRefExoticComponent<
React.RefAttributes<HTMLDivElement>
>;
export const htmlTest: React.ForwardRefExoticComponent<
React.RefAttributes<HTMLElement>
> = divTest;
打字稿错误信息:
Type 'ForwardRefExoticComponent<RefAttributes<HTMLDivElement>>' is not assignable to type 'ForwardRefExoticComponent<RefAttributes<HTMLElement>>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'RefAttributes<HTMLElement>' is not assignable to type 'RefAttributes<HTMLDivElement>'.
在最后一行中,它指出我正在尝试将 RefAttributes<HTMLElement>
分配给 RefAttributes<HTMLDivElement>
,但我以相反的方式进行分配(如第一行正确显示)。
我错过了什么吗?因为我假设具有更具体的 HTMLDivElement 引用的组件可以分配给具有更通用的 HTMLElement 引用的组件。
解决方法
可以由 ref
转发的 forwardRef
类型之一是回调引用。如果您处理过传递回调,那么您就会知道 extends
在处理回调时有点“向后”。但 forwardRef
也可以转发 RefObject
。
由于您要处理对象和回调的联合,因此您需要精确正确的引用类型。它不能更宽或更窄。
这里有一些例子来澄清它:
// ok
const f = (ref: (instance: HTMLDivElement | null) => void) => <div ref={ref}/>
// ok
const f = (ref: MutableRefObject<HTMLDivElement | null>) => <div ref={ref}/>
// ok because HTMLDivElement extends HTMLElement
const f = (ref: (instance: HTMLElement | null) => void) => <div ref={ref}/>
// error because HTMLElement is not assignable to HTMLDivElement
const f = (ref: MutableRefObject<HTMLElement | null>) => <div ref={ref}/>
// error because a div ref can only be assigned to a div
const f = (Element: "div" | "a",ref: MutableRefObject<HTMLDivElement | null>) => <Element ref={ref}/>
// error because we need a more exact ref type
const f = (Element: "div" | "a",ref: MutableRefObject<HTMLElement | null>) => <Element ref={ref}/>
// ok - the only possible ref here must be both a div and an a
const f = (Element: "div" | "a",ref: MutableRefObject<(HTMLDivElement & HTMLAnchorElement) | null>) => <Element ref={ref}/>
我原以为这是一个错误,但显然不是。
const f = (Element: "div" | "a",ref: (instance: (HTMLDivElement & HTMLAnchorElement) | null) => void) => <Element ref={ref}/>
所以现在我偶然发现了一个可能的解决方案,即您的 ref 可以是所有单个 ref 类型的交集。
如果不知道 HOC
的作用,很难说出最佳解决方案是什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。