This error means a class that inherits from another class (a "derived class") failed to call the parent class’s constructor using super().
Here’s what’s actually broken: the derived class’s constructor is trying to access this before the parent class’s initialization is complete, which is a fundamental rule of JavaScript/TypeScript class inheritance. The super() call is what ensures the parent class’s setup happens first, making this a valid, initialized object for the derived class to work with.
Common Causes and Fixes
-
Missing
super()Call Entirely:- Diagnosis: Look for a derived class constructor that doesn’t have a
super()call as its first statement. - Fix: Add
super()as the very first line in the derived class’s constructor.
Fixed:class Parent { constructor(public name: string) {} } class Child extends Parent { constructor(public age: number) { // Missing super() here this.age = age; // Error occurs here } }class Parent { constructor(public name: string) {} } class Child extends Parent { constructor(public age: number) { super("defaultName"); // Call parent constructor this.age = age; } } - Why it works:
super()invokes the parent class’s constructor, setting up the inherited properties and methods before the child class can add its own.
- Diagnosis: Look for a derived class constructor that doesn’t have a
-
super()Called After OtherthisReferences:- Diagnosis: The
super()call exists but is not the first statement in the constructor. Any use ofthisbeforesuper()will trigger the error. - Fix: Move the
super()call to be the absolute first statement.
Fixed:class Parent { constructor(public id: number) {} } class Child extends Parent { constructor(public id: number, public label: string) { console.log(this.id); // Error: 'this' is used before super() super(id); } }class Parent { constructor(public id: number) {} } class Child extends Parent { constructor(public id: number, public label: string) { super(id); // Call parent constructor first console.log(this.id); // Now this.id is valid this.label = label; } } - Why it works: JavaScript enforces that
thisis not accessible until the parent constructor has completed its initialization viasuper().
- Diagnosis: The
-
Derived Class Has No Constructor (But Parent Does):
- Diagnosis: If a derived class doesn’t define its own constructor, TypeScript implicitly provides one. If the parent class has a constructor that requires arguments, and the derived class doesn’t define its own constructor to pass those arguments up, you’ll get this error.
- Fix: Define a constructor in the derived class that calls
super()with the necessary arguments.
Example leading to TS2377:class Vehicle { constructor(public wheels: number) {} } class Car extends Vehicle {} // No constructor here // If Vehicle's constructor required an argument, this would error. // For example, if Vehicle had constructor(public brand: string, public wheels: number) {} // and you tried to create `new Car()`, it would fail because `wheels` is missing. // The TS2377 error is more subtle: it happens when the *parent* requires *arguments* // and the child *omits* its constructor, meaning the parent's constructor isn't called.
Fixed:class ParentWithArgs { constructor(public value: string) {} } class ChildNoConstructor extends ParentWithArgs { // No constructor defined here } // const instance = new ChildNoConstructor(); // This would cause TS2377 if ParentWithArgs required args. // The *actual* TS2377 error arises when the derived class *has* a constructor, but doesn't call super. // Let's illustrate the *common* scenario leading to TS2377, which is a derived class *with* a constructor. class Base { constructor(public message: string) {} } class Derived extends Base { constructor(public data: number) { // If Base required arguments and this Derived class constructor // doesn't call super() with them, TS2377 occurs. // The most direct TS2377 is when super() is missing entirely or misplaced. // Let's focus on the direct error: // this.data = data; // Error: This is where the error is caught, but the root is missing super() } }class Base { constructor(public message: string) {} } class Derived extends Base { constructor(public message: string, public data: number) { super(message); // Pass arguments to parent constructor this.data = data; } } - Why it works: By defining a constructor in the derived class and explicitly calling
super()with the arguments expected by the parent’s constructor, you ensure the parent is properly initialized.
-
super()Called Conditionally:- Diagnosis:
super()is inside anifstatement or is otherwise not guaranteed to be called on every code path through the constructor. - Fix: Ensure
super()is called unconditionally at the beginning of the constructor.
Fixed:class Configurable { constructor(public setting: string | undefined) {} } class Widget extends Configurable { constructor(public name: string, setting?: string) { if (setting) { super(setting); // super() is conditional } this.name = name; } }class Configurable { constructor(public setting: string | undefined) {} } class Widget extends Configurable { constructor(public name: string, setting?: string) { super(setting); // Call super unconditionally this.name = name; } } - Why it works: The
super()call must execute for every instance of the derived class to correctly set up its inherited state.
- Diagnosis:
-
Abstract Base Class Constructor Not Called (Less Common but Possible):
- Diagnosis: If your base class is
abstractand has a constructor, a concrete derived class must still callsuper(). Theabstractkeyword doesn’t exempt derived classes from constructor initialization rules. - Fix: Add
super()to the derived class’s constructor.
Fixed:abstract class AbstractBase { constructor(public id: string) { console.log("AbstractBase initialized with", id); } } class ConcreteChild extends AbstractBase { constructor(public id: string, public value: number) { // Missing super() this.value = value; // Error here } }abstract class AbstractBase { constructor(public id: string) { console.log("AbstractBase initialized with", id); } } class ConcreteChild extends AbstractBase { constructor(public id: string, public value: number) { super(id); // Call parent constructor this.value = value; } } - Why it works: Even though the abstract class cannot be instantiated directly, its constructor’s logic (if any) must run to initialize inherited properties for any concrete subclass.
- Diagnosis: If your base class is
-
Inheriting from a Class with a Constructor that Throws:
- Diagnosis: If the parent class’s constructor throws an error, and the derived class’s constructor doesn’t handle it or is structured such that
super()is called after a point where the error might occur, you might see this. However, TS2377 specifically relates to the structure of the derived constructor, not necessarily the parent’s runtime behavior. The most direct cause is still structural. - Fix: Ensure
super()is the first statement. If the parent constructor itself has a bug that causes it to throw, that’s a separate issue to debug in the parent class.
Fix: The fix remains the same: ensureclass FaultyParent { constructor() { if (true) { // Example of a condition that might lead to an error throw new Error("Parent initialization failed!"); } } } class ChildOfFaulty extends FaultyParent { constructor() { // If FaultyParent's constructor throws, this error might manifest // as TS2377 if the derived constructor isn't structured correctly, // but more likely, you'd just see the thrown error from FaultyParent. // The TS2377 specifically points to the derived class's failure to call super. super(); // This line is essential for TS2377 // If super() itself throws, the error is from the parent. // If super() is *missing*, TS2377 is the compile-time error. } }super()is the first statement. The underlying issue of the parent throwing must be addressed separately. - Why it works:
super()is the gateway. If it’s correctly placed, the derived class acknowledges its dependency on the parent’s initialization.
- Diagnosis: If the parent class’s constructor throws an error, and the derived class’s constructor doesn’t handle it or is structured such that
The next error you might encounter after fixing this is related to how you’re passing arguments to super(), or if the parent class’s constructor has other unmet preconditions.