Abhishek
Abhishek

Reputation: 351

React + typescript inheritance and extending property

I am creating a component which will be extended in future, for that i need to make it more generic.

I have a requirement something like below.

I have a class Base which accepts properties of type 'cell' and 'phone'.

I want to extend that in NewBase class and support new property newType.

The error I am getting is

[ts] This condition will always return 'false' since the types '"cell" | "phone"' and '0' have no overlap.

I am not getting enough ideas to extend the interface to support the new class Please Help...

export interface IBaseType {
    type: 'cell' | 'phone' 
} 
export class Base extends React.Component<IBaseType > {
    public render() {
        const { name, type } = this.props;
        return (() => {
            switch (type) {
                case 'cell': return <h1>Cell</h1>
                case 'phone': return <h1>Phone</h1>
            }
        })()
    } 
}

interface NewType extends Omit<IBaseType, 'type'>  {
    type: 'newType' | IBaseType['type']
 }

class NewBase extends Base {
    constructor(props: NewType){}
    public render(){
       if(this.props.type === 'newType') {
          return <h1>Hi i am new type</h1>
       }
       return super.render();
    }
}

Upvotes: 0

Views: 2483

Answers (1)

Matt McCutchen
Matt McCutchen

Reputation: 30879

The type of this.props is determined by the props type argument you pass to React.Component. In this scenario where NewBase extends Base and Base extends React.Component<IBaseType>, the type of this.props is still IBaseType, which explains the error. If you want to be able to define subclasses of Base that have different props types, you'll need to add a type parameter to Base for the props type. Something like this may work for you:

interface ICommonType {
    type: string;
}
export interface IBaseType {
    type: 'cell' | 'phone' 
} 
export class Base<P extends ICommonType = IBaseType> extends React.Component<P> {
    public render() {
        const { name, type } = this.props;
        return (() => {
            switch (type) {
                case 'cell': return <h1>Cell</h1>
                case 'phone': return <h1>Phone</h1>
            }
        })()
    } 
}

interface NewType extends Omit<IBaseType, 'type'>  {
    type: 'newType' | IBaseType['type']
 }

class NewBase extends Base<NewType> {
    public render(){
       if(this.props.type === 'newType') {
          return <h1>Hi i am new type</h1>
       }
       return super.render();
    }
}

Upvotes: 4

Related Questions