使用redux-thunk连接抽象类与Redux状态时的类型错误问题
React+Redux-Thunk抽象类组件类型错误解决方案
问题场景
我在React中结合Redux-Thunk与类组件使用时,有一套基础模式可以正常导出关联Redux状态的组件:
import React from 'react'; import { ThunkDispatch } from 'redux-thunk'; import { connect, ConnectedProps } from 'react-redux'; type OwnProps = { /* 自定义属性 */ } const mapStateToProps = (state: RootState, ownProps: OwnProps) => { return { /* 映射的状态 */ } } const mapDispatchToProps = (dispatch: ThunkDispatch)=>{ return { /* 绑定的action */ } } const connector = connect(mapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps<typeof connector>; type Props = PropsFromRedux & OwnProps; type LocalState = { /* 组件内部状态 */ } class MyClass___ extends React.PureComponent<Props, LocalState> { // 组件逻辑 } export const MyClass = connector(MyClass___)
但当我把MyClass___定义为抽象类,用来封装通用功能作为基类时,最后一行会出现TypeScript错误:
Argument of type 'typeof MyClass___' is not assignable to parameter of type 'ComponentType<never>'. Type 'typeof MyClass___' is not assignable to type 'ComponentClass<never, any>'. Cannot assign an abstract constructor type to a non-abstract constructor type.
解决方案
TypeScript不允许把抽象类直接传给connect,因为connect期望接收一个可实例化的组件类。可以通过以下两种方式解决:
方式1:用中间类包裹抽象基类
先定义封装通用逻辑的抽象基类,再创建一个空的非抽象中间类继承它,最后把中间类传给connect:
import React from 'react'; import { ThunkDispatch } from 'redux-thunk'; import { connect, ConnectedProps } from 'react-redux'; type OwnProps = { /* 自定义属性 */ } const mapStateToProps = (state: RootState, ownProps: OwnProps) => { return { /* 映射的状态 */ } } const mapDispatchToProps = (dispatch: ThunkDispatch)=>{ return { /* 绑定的action */ } } const connector = connect(mapStateToProps, mapDispatchToProps); type PropsFromRedux = ConnectedProps<typeof connector>; type Props = PropsFromRedux & OwnProps; type LocalState = { /* 组件内部状态 */ } // 定义抽象基类,封装通用逻辑 abstract class AbstractBaseClass extends React.PureComponent<Props, LocalState> { // 通用方法或抽象方法 abstract renderContent(): React.ReactNode; render() { return <div>{this.renderContent()}</div>; } } // 创建非抽象的中间类,仅继承抽象基类 class MyClassImpl extends AbstractBaseClass {} // 连接中间类并导出 export const MyClass = connector(MyClassImpl);
方式2:类型断言绕过检查
如果不想额外创建中间类,可以用类型断言告诉TypeScript,确认该抽象类可被当作普通组件类处理:
// ... 前面的类型定义和抽象类代码保持不变 export const MyClass = connector(MyClass___ as typeof React.ComponentClass<Props>);
原理说明
connect的参数类型ComponentType要求传入的类是可实例化的非抽象类,而抽象类因包含未实现的抽象方法,TypeScript判定它不能直接被实例化,因此抛出类型错误。两种解决方案本质都是让TypeScript认可传入的类符合ComponentType的要求。
内容的提问来源于stack exchange,提问作者Marcus Junius Brutus
相关产品推荐
相关产品推荐

