Notes/React

React and TypeScript Gymnastics

Various tips and tricks to for working with React and TypeScript. With some creativity, a lot of the techniques shown here can be applied to JavaScript documented with TypeScript compatible JSDoc annotations.

This will be expanded over time.

Extract Props From Component

Newer versions of @types/react include a helper to extract a components props type information when it doesn't export a dedicated props type. Handy when building abstractions.

React.ComponentProps<typeof TargetComponent>

React Redux Connector

Newer versions of React Redux use strategies similar to below to guide implementors using TypeScript. Some adjustments may be necessary if on older versions (such as casting to address type definition flaws).

// redux/state.ts


export type ReduxState = {
    someState: {
        // ...
    },
    // ...
};

// ...
// some-component.tsx
import React from "react"; 
import { Dispatch, connect } from "react-redux";
import { ReduxState } from "./redux/state.js";
import { someAction } from "./redux/action-creators.js";

type StateProps = ReturnType<typeof mapStateToProps>;

type DispatchProps = typeof mapDispatchToProps;

interface OwnProps {
    // ...
};

type Props = StateProps & DispatchProps & OwnProps;

function SomeComponent(props: Props): React.JSX {
    // ...
}

function mapStateToProps(state: ReduxState) {
    return {
        someState: state.someState,
    };
}

const mapDispatchToProps = {
    someAction,
};

export default connect<StateProps, DispatchProps, OwnProps>(
    mapStateToProps,
    mapDispatchToProps
)(SomeComponent as any as React.ComponentClass<Props>);

Stuck with React.createClass or createReactClass

Suppose you are stuck on an old version of React or have legacy components which have yet to be refactored to the newer class Component's and function components. TypeScript is rather terrible when it comes to providing type safety here, and I don't blame it. The create class wrapper is a weird and long deprecated monster.

Avoid this hell if you can, failing that there are some ways to give TypeScript a helping hand.

State and Props

The best solution I've found so far is to assign the state and props to a local variable, and explicitly declare the type (this assums you have dedicated types already for the state and props).

// ...
import createReactClass from "create-react-class";

type State = {
    // ...
};
type Props = {
    // ...
};

export default createReactClass({
    // ...

    render() {
        const state: State = this.state;
        const props: Props = this.props;

        // ...
    }
});