The problem is that the call to getData within the Parent constructor happens before the assignment of the parameter item to the private field item. That's because the automatic initialization happens after the super() call, not before it. See *** comments:
abstract class Parent {
constructor() {
console.log(this.getData()); // *** Calls Child's getData
}
abstract getData(): string;
}
class Child extends Parent {
constructor(private item: any) {
super(); // *** Calls Parent's constructor
// ** Automatic initialization happens here, *after* the `super()` call
}
getData(): string {
return this.item.id; // *** So here, `this.item` is `undefined`
}
}
new Child({id: 'Hello World!'});
This is one of the reasons calling methods from constructors is generally not best practice: They can be overridden by child classes, but the child class's initialization may not be complete (as in your case).