我有一个简单的组件,用react-redux包装,我有一个ref到该组件与forwardRef: true
,像这样:
// Button.tsx
class Button extends React.Component {
// ...
}
// ...
export default connect(mapStateToProps, null, null, { forwardRef: true })(Button);
现在我有一个父组件来呈现Button组件
// ButtonParent.tsx
import Button from './Button';
class ButtonParent extends React.Component {
buttonRef: React.RefObject<Button>;
public constructor(props) {
this.buttonRef = React.createRef()
}
render() {
return (
<>
<Button ref={this.buttonRef}/>
</>
);
}
}
请注意,这是该问题的最小简化再现,没有不必要的输入。
问题在于buttonRef
的类型。将Button
(Button.tsx
的默认导出)分类为一个值,是正确的。它还建议我使用typeof
,这是不正确的。
这个问题源于Button
是redux连接的HOC,但ref的类型是实际的Button
类组件。
可以通过重命名和重新导出Button
组件来解决这个问题,如下所示:
// Button.tsx
class _Button extends React.Component {
// ...
}
// ...
export default connect(mapStateToProps, null, null, { forwardRef: true })(_Button);
,然后使用buttonRef: React.RefObject<_Button>
.
但是我想知道是否有一种更容易/更干净的方法来做到这一点,也许redux以某种方式导出包装组件的类型,我只是不知道如何?
编辑:一个更简单的提取类型:
type WrappedComponentType<C extends { WrappedComponent: any }> = InstanceType<C['WrappedComponent']>;
我问这个问题差不多一年前,今天我遇到了一个类似的问题,最终又找到了这个线程。在过去的一年里,我对TypeScript有了更好的了解,所以我决定重新解决这个问题,并尝试解决这个问题,幸运的是我找到了一个解决方案!
您可以通过使用redux的ConnectedComponent
类型来推断类型:
import React from "react";
import { ConnectedComponent } from "react-redux";
type WrappedComponentType<C> = C extends ConnectedComponent<any, infer T>
? T extends { ref?: React.LegacyRef<infer WrappedComponent> | undefined }
? WrappedComponent
: never
: never;
和buttonRef
:
this.buttonRef = React.createRef<WrappedComponentType<typeof Button>>();
如果你使用功能组件:
let buttonRef = useRef<WrappedComponentType<typeof Button>>(null);