Solution 1:

Alternative Solution:

This answer of Thierry Templier is an alternative way to get around the problem.

After some questions with Thierry Templier, I came to the following working example that meets my expectations as an alternative to inheritance limitation mentioned in this question:

1 - Create custom decorator:

export function CustomComponent(annotation: any) {
  return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);

    var parentAnnotation = parentAnnotations[0];
    Object.keys(parentAnnotation).forEach(key => {
      if (isPresent(parentAnnotation[key])) {
        // verify is annotation typeof function
        if(typeof annotation[key] === 'function'){
          annotation[key] = annotation[key].call(this, parentAnnotation[key]);
        }else if(
        // force override in annotation base
        !isPresent(annotation[key])
        ){
          annotation[key] = parentAnnotation[key];
        }
      }
    });

    var metadata = new Component(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
  }
}

2 - Base Component with @Component decorator:

@Component({
  // create seletor base for test override property
  selector: 'master',
  template: `
    <div>Test</div>
  `
})
export class AbstractComponent {

}

3 - Sub component with @CustomComponent decorator:

@CustomComponent({
  // override property annotation
  //selector: 'sub',
  selector: (parentSelector) => { return parentSelector + 'sub'}
})
export class SubComponent extends AbstractComponent {
  constructor() {
  }
}

Plunkr with complete example.

Solution 2:

Angular 2 version 2.3 was just released, and it includes native component inheritance. It looks like you can inherit and override whatever you want, except for templates and styles. Some references:

  • New features in Angular 2.3

  • Component Inheritance in Angular 2

  • A Plunkr demonstrating component inheritance

Solution 3:

Let us understand some key limitations & features on Angular’s component inheritance system.

The component only inherits the class logic:

  • All meta-data in the @Component decorator is not inherited.
  • Component @Input properties and @Output properties are inherited.
  • Component lifecycle is not inherited.

These features are very important to have in mind so let us examine each one independently.

The Component only inherits the class logic

When you inherit a Component, all logic inside is equally inherited. It is worth noting that only public members are inherited as private members are only accessible in the class that implements them.

All meta-data in the @Component decorator is not inherited

The fact that no meta-data is inherited might seem counter-intuitive at first but, if you think about this it actually makes perfect sense. If you inherit from a Component say (componentA), you would not want the selector of ComponentA, which you are inheriting from to replace the selector of ComponentB which is the class that is inheriting. The same can be said for the template/templateUrl as well as the style/styleUrls.

Component @Input and @Output properties are inherited

This is another feature that I really love about component Inheritance in Angular. In a simple sentence, whenever you have a custom @Input and @Output property, these properties get inherited.

Component lifecycle is not inherited

This part is the one that is not so obvious especially to people who have not extensively worked with OOP principles. For example, say you have ComponentA which implements one of Angular’s many lifecycle hooks like OnInit. If you create ComponentB and inherit ComponentA, the OnInit lifecycle from ComponentA won't fire until you explicitly call it even if you do have this OnInit lifecycle for ComponentB.

Calling Super/Base Component Methods

In order to have the ngOnInit() method from ComponentA fire, we need to use the super keyword and then call the method we need which in this case is ngOnInit. The super keyword refers to the instance of the component that is being inherited from which in this case will be ComponentA.