Kousha
Kousha

Reputation: 36189

How to extend React class in typescript

Here is a simple example:

interface BaseProps {
    name: string;
}

class BaseClass<P extends BaseProps> extends React.Component<P, void> {

}

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {

} 

I'm expecting that SuperClass by default would have this.props.name. But right now, I'm getting a compilation error, saying Type 'SuperProps' does not satisfy the constraint 'BaseProps'.Property 'name' is missing in type 'SuperProps'.

What am I doing wrong? I realize I can do SuperProps extends BaseProps but that seems redundant here.

Upvotes: 6

Views: 4965

Answers (2)

justin
justin

Reputation: 3607

Now say you couldn't modify BaseClass (3rd party code) such that it takes a generic type i.e.

class BaseClass extends React.Component<BaseProps, void> {

}

You should still be able to redefine BaseClass with extended prop types like so:

const SuperClass = BaseClass as React.ComponentClass<
  BaseProps & {
    somethingElse: string;
  }
>;

Full e.g. where SomeInput actually supports autoFocus prop but it's exported prop type defs do not:

import { Input as SomeInput, InputPropsType as SomeInputPropsType } from 'somewhere';

const Input = SomeInput as React.ComponentClass<
  SomeInputPropsType & {
    autoFocus?: boolean;
  }
>;

// Now passing `autoFocus` prop to `Input` should be fine

Upvotes: 0

Hardik Modha
Hardik Modha

Reputation: 12736

class BaseClass<P extends BaseProps> extends React.Component<P, void>

where <P extends BaseProps> means any valid type which extends BaseProps is assignable to BaseClass. This is how the generics works.

Now, when you do

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {

} 

You are assigning the type SuperProps which does not extend the BaseProps. That is the reason you are getting the error.

To overcome the error, as you said you either need to extend the BaseProps interface or you can use intersection types. If you use intersection types then the complete example will look like:

export interface BaseProps {
    name: string;
}

class BaseClass<P> extends React.Component<P & BaseProps, void> {

}

interface SuperProps {

}

class SuperClass extends BaseClass<SuperProps> {
    render(): JSX.Element {
        return (
            <div>
                {this.props.name} {/* Won't throw an error*/}
            </div>
        );
    }
}

You can read more about advanced-types here.

Upvotes: 7

Related Questions