Daniel Pérez Daniel Pérez - 2 months ago 19
React JSX Question

Inherit from react component

Hello I'm using typescript + react, and I want to have a base class and several components inherit from the base class.

import * as React from "react";

interface IBaseProps {
title: string;
}

class Base<P extends IBaseProps, S> extends React.Component<P, S> {
public props: IBaseProps;

public render() {
return (
<h1> Generic Class {this.props.title} </h1>
);
}
}

interface IChildProps extends IBaseProps {
message: string;
}

class Child extends React.Component<IChildProps, undefined> {

public render() {
return (
<h1> Child Class {this.props.title} {this.props.message} </h1>
);
}
}


But when compiling it throws an error:

TS2415: Class 'Base<P, S>' incorrectly extends base class 'Component<P, S>'.
Types of property 'props' are incompatible.
Type 'IBaseProps' is not assignable to type 'Readonly<{ children?: ReactNode; }> & Readonly<P>'.
Type 'IBaseProps' is not assignable to type 'Readonly<P>'.


The problem is not inheriting, even this got me the error

export class Base<P, S> extends React.Component<P, S> {
public props: IBaseProps;

public render() {
return (
<h1> Generic Component </h1>
);
}
}


I'm using typescript
v2.3.4
, in case it matter

Answer Source

There's no need to define the props member twice, it's enough to do so in the base class:

class Base<P extends IBaseProps, S> extends React.Component<P, S> {
    public props: IBaseProps;

    ...
}

class Child extends React.Component<IChildProps, undefined> {
    public render() {
        ...
    }
}

The type of Child.props will be IChildProps because that's what you passed as the generic constraint.

But you don't even need to define it in the base class because React.Component will already do that for you, so it should just be:

class Base<P extends IBaseProps, S> extends React.Component<P, S> {
    public render() {
        ...
    }
}

class Child extends React.Component<IChildProps, undefined> {
    public render() {
        ...
    }
}

And you will still have this.props (with the right type) in all components.