How to use TypeScript with withRouter, connect, React.Component and custom properties? How to use TypeScript with withRouter, connect, React.Component and custom properties? reactjs reactjs

How to use TypeScript with withRouter, connect, React.Component and custom properties?


How I do it in our projects (this is the easiest way and you can get intellisense when you use it):

import * as React from 'react'import { connect } from 'react-redux';import { withRouter, RouteComponentProps } from 'react-router';import {   fetchTestLists,  newTestList,  displayTestList,} from '../../../actions/index';interface StateProps {  testList: any;    // todo: use the type of state.myList to have validation on it}interface DispatchProps {  fetchTestLists: () => void;  newTestList: () => void;  displayTestList: (any) => void;   // todo: replace any with the actual type}interface Props extends RouteComponentProps {      // custom properties passed to component  className: string;}type PropsType = StateProps & DispatchProps & Props;class MyTest extends React.Component<PropsType> {  constructor(props) {    super(props);    this.handleCellClick = this.handleCellClick.bind(this);    this.newTestList = this.newTestList.bind(this);  }  componentDidMount() {    this.props.fetchTestLists();  }  handleCellClick(row, column, event) {    this.props.displayTestList(row);  }  newTestList(e) {    this.props.newTestList()  }  render() {    return (      <div className={this.props.className}>      </div>    );  }}const mapStateToProps = (state, ownProps: Props): StateProps => ({  testList: state.myList,   // todo: define a type for the root state to have validation here});const dispatchToProps: DispatchProps = {  fetchTestLists,  newTestList,  displayTestList,};export default withRouter(connect(  mapStateToProps,  dispatchToProps,)(MyTest));

Also if this is something you will type often I recommend writing a custom snippet (if you are using something like VS Code it is very easy).


I try to rewrite your example and end up with this code:

import * as React from 'react';import { connect } from 'react-redux';import { RouteComponentProps, withRouter } from 'react-router';import {   fetchTestLists,  newTestList,  displayTestList,} from '../../../actions/index';import { Dispatch, bindActionCreators, AnyAction } from 'redux';interface IStateProps {  testList: IListType;    // todo: use the type of state.myList to have validation on it}interface IDispatchProps {  fetchTestLists: () => AnyAction;  newTestList: () => AnyAction;  displayTestList: (value: string) => AnyAction;   // todo: replace any with the actual type}interface IProps {      // custom properties passed to component  className: string;}type PropsType = IStateProps & IDispatchProps & IProps;class MyTestComponent extends React.Component<PropsType & RouteComponentProps<{}>, {}> {  constructor(props: PropsType & RouteComponentProps<{}>) {    super(props);    this.handleCellClick = this.handleCellClick.bind(this);    this.newTestList = this.newTestList.bind(this);  }  public componentDidMount() {    this.props.fetchTestLists();  }  public handleCellClick(row, column, event) {    this.props.displayTestList(row);  }  public newTestList(e) {    this.props.newTestList();  }  public render(): JSX.Element {    return (      <div className={this.props.className}>      </div>    );  }}export const MyTest = connect(  (state: IAppState, ownProps: IProps) => ({      testList: state.testList,      ...ownProps,  }),  (dispatch: Dispatch) => bindActionCreators<AnyAction, Pick<IDispatchProps, keyof IDispatchProps>>(    { displayTestList, fetchTestLists, newTestList },    dispatch,),)(withRouter(MyTestComponent));interface IListType {  someProp: string;}interface IAppState {  testList: IListType;  differentList: IListType;}

I have changed export default on to assigning result of wrapped MyTestComponent class with connect and withRouter HOC into MyTest. Then I import MyTest component like this

import { MyTest } from './MyTest' 

I have added interfaces to describe all properties which have been passed from Parent component, also use withRouter and connect in different way (more readable for me).

I hope it will be helpful


I solved this issue by forcing an install of the @types/react-redux package. I had just updated from 4.4.5 to 5.0.15.

It might be worth while to run a fresh npm install --save @types/react-redux@5.0.15.