Manfred Steiner
Manfred Steiner

Reputation: 1295

Strange Typescript inheritance on Angular 2 Guide Tutorial DI

In the Angular 2 guide Dependency Injection (in the first chapter Why dependency injection?) there are some strange lines of code. They work, but I don't know why. You can also find the running example on https://angular.io/resources/live-examples/dependency-injection/ts/eplnkr.html.

In the file car.ts the class Engine and the class Car are declared as:

export class Engine { 
  public cylinders = 4; 
}

export class Car {
  public description = 'DI';

  constructor(public engine: Engine, public tires: Tires) { }
  ...
}

In the file car-creation.ts the class Car is used ...

import { Car, Engine, Tires } from './car';

class Engine2 {
  constructor(public cylinders: number) { }
}

export function superCar() {
  // Super car with 12 cylinders and Flintstone tires.
  let bigCylinders = 12;
  let car = new Car(new Engine2(bigCylinders), new Tires());
  car.description = 'Super';
  return car;
}

It works without warnings or errors by the Typescript compiler.

Strange! Why it is possible to create car with a wrong engine type?
new Engine2(...) creates an object from class Engine2 which is not derived from class Engine.

Is this behavior a bug or a feature of Typescript?

I would expect the following lines of code in the file car-creation.ts.

class Engine2 extends Engine {
  constructor(public cylinders: number) {
    super();
  }
}

... or ...

class Engine2 extends Engine {
  constructor(cylinders: number) {
    super(); 
    this.cylinders = cylinders;
  }
}

Upvotes: 0

Views: 103

Answers (1)

Sebastian Sebald
Sebastian Sebald

Reputation: 16856

TypeScript uses structural typing instead of nominal typing. You can find more on the topic here. Even though you're writing class it is not a ... class in the sense of class-inheritance. It's just syntax sugar for creating a Prototype.

class Engine2 {
  constructor(public cylinders: number) { }
}

class Engine { 
  public cylinders = 4; 
}

Even though they do not inherit from each other, they a the same on a structural level. Both have a public member cylinders that is a number. While Engine will always have 4 cylinders, you can init Engine2 with any number of cylinders.

Writing the constructor like constructor(public cylinders: number) {} is syntax sugar for initializing a public member.

Upvotes: 1

Related Questions