angulartypescriptinheritance

Angular typescript class incorrectly extends base class, type of property are incompatbile


angular 5, In class 'RecordManagerComponent' there is an public object property 'info' defined as follow:

      export class RecordManagerComponent {
          public info: { form_status: string, proj_title_cntr_no: string, block_t: 
               string, floor: string, contractor: string, test: string };
        .....
      }

then I create another class extends from 'RecordManagerComponent' named 'F48ItemSearchComponent' and defined an object property 'info' as follow:

    export class F48ItemSearchComponent extends RecordManagerComponent {
        public info: { form_status: string, proj_title_cntr_no: string, block_t: 
             string, floor: string, contractor: string };
        .....
    }

but there is error as follow:

ERROR in src/app/structure/inspect/components/f48/f48-item-search/f48-item-search.component.ts(33,14): error TS2415: Class 'F48ItemSearchComponent' incorrectly extends base class 'RecordManagerComponent'. Types of property 'info' are incompatible. Type '{ form_status: string; proj_title_cntr_no: string; block_t: string; floor: string; contractor: st...' is not assignable to type '{ form_status: string; proj_title_cntr_no: string; block_t: string; floor: string; contractor: st...'. Two different types with this name exist, but they are unrelated. Property 'test' is missing in type '{ form_status: string; proj_title_cntr_no: string; block_t: string; floor: string; contractor: st...'.

why? I must rename the 'info' in child class 'F48ItemSearchComponent'?


Solution

  • First define a common interface which contains all the properties required by the children. We define all derived properties to be ?: optional, so that they are not mandatory when inherited.

    export interface Info {
      form_status: string;
      proj_title_cntr_no: string;
      block_t: string;
      floor: string;
      contractor: string;
      test?: string;
    }
    

    If you are using typescript >= 3.5 Try below additional step, else above solution is enough:

    Then we can use the typescript utility Omit to exclude test, so that test is not suggested by Intellisense and since it is optional there is no error.

    export type F48ItemSearchInfo = Omit<Info, 'test'>;
    

    The definitions come from the same interface, but we can derive sub types using Omit. You also have the vice versa method Pick to select only certain properties from an interface.

    Full Code:

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    
    export interface Info {
      form_status: string;
      proj_title_cntr_no: string;
      block_t: string;
      floor: string;
      contractor: string;
      test?: string;
    }
    
    export type F48ItemSearchInfo = Omit<Info, 'test'>;
    
    @Component({
      selector: 'app-parent',
      template: '',
    })
    export class Parent {
      public info!: Info;
    }
    
    @Component({
      selector: 'app-root',
      template: `
        <a target="_blank" href="https://angular.dev/overview">
          Learn more about Angular
        </a>
      `,
    })
    export class App extends Parent {
      public override info!: F48ItemSearchInfo;
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo