How to fix 'super' must be called before accessing properties on 'this' in a derived class in TypeScript
This TypeScript/JavaScript error occurs when you try to access properties or methods using "this" in a derived class constructor before calling the parent class constructor with super(). The parent class must be initialized first before the derived class can safely use its own properties.
Quick fix
Fixes 'super' must be called before accessing properties on 'this' in a derived class
// ❌ WRONG: Accessing "this" before super()
class Derived extends Base {
constructor(value: string) {
this.someProperty = value; // Error: "this" before super()
super();
}
}
// ✅ CORRECT: Call super() first
class Derived extends Base {
constructor(value: string) {
super(); // Parent initialized first
this.someProperty = value; // Now safe to use "this"
}
}- Move super() call to the beginning of the constructor
- Pass arguments to super() if needed
- Fix property initializers that use "this"
- Handle parameter properties with "this" references
// ❌ WRONG: Accessing "this" before super()class Derived extends Base {constructor(value: string) {this.someProperty = value; // Error: "this" before super()super();}}// ✅ CORRECT: Call super() firstclass Derived extends Base {constructor(value: string) {super(); // Parent initialized firstthis.someProperty = value; // Now safe to use "this"}}'super' must be called before accessing properties on 'this' in a derived class
What this error means
The error "'super' must be called before accessing properties on 'this' in a derived class" is a fundamental JavaScript/TypeScript rule enforcement. In class-based inheritance, when you extend a parent class, the derived class's constructor must call super() before it can access the "this" keyword. This is because: 1. **Parent initialization first**: The parent class constructor needs to set up the instance first 2. **"this" is undefined**: Before super() is called, "this" doesn't refer to a valid object 3. **Inheritance chain**: Properties and methods from the parent class aren't available until after super() The error prevents runtime errors where you might try to access properties that haven't been initialized yet. This is especially important in TypeScript with strict class initialization checking enabled.
Typical symptoms
- TypeScript compiler error: "super must be called before accessing this in derived class"
- JavaScript runtime error in strict mode when accessing "this" before super()
- Code fails to compile with TypeScript strict mode enabled
- IDE shows red squiggly lines under "this" references before super() call
- Class properties appear undefined when accessed before parent initialization
Common causes
- Accessing "this" keyword in derived class constructor before calling super()
- Trying to initialize derived class properties before parent class is ready
- Calling methods that use "this" before the parent constructor completes
- Using "this" in parameter default values or property initializers that run before super()
- Forgetting to call super() at the beginning of the derived constructor
How to fix "'super' must be called before accessing properties on 'this' in a derived class"
The most common fix is to ensure super() is called before any "this" references:
// ❌ WRONG: Accessing "this" before super()
class Derived extends Base {
constructor(value: string) {
this.someProperty = value; // Error: "this" before super()
super();
}
}
// ✅ CORRECT: Call super() first
class Derived extends Base {
constructor(value: string) {
super(); // Parent initialized first
this.someProperty = value; // Now safe to use "this"
}
}Always call super() as the first statement in your derived class constructor.
If the parent class constructor requires arguments, pass them to super():
// ❌ WRONG: Trying to process data before passing to parent
class User extends Person {
constructor(name: string, age: number) {
const processedName = name.trim(); // Error: "this" not available yet
super(processedName, age);
}
}
// ✅ CORRECT: Process arguments before constructor, or pass directly
class User extends Person {
constructor(name: string, age: number) {
// Process arguments before calling super()
const processedName = name.trim();
super(processedName, age); // Parent gets processed values
}
}
// ✅ ALTERNATIVE: Use a factory method if complex processing is needed
class User extends Person {
private constructor(name: string, age: number) {
super(name, age);
}
static create(name: string, age: number): User {
const processedName = name.trim();
return new User(processedName, age);
}
}Property initializers that reference "this" can cause this error:
// ❌ WRONG: Property initializer using "this" before super()
class Derived extends Base {
private calculatedValue = this.computeValue(); // Error: "this" in initializer
constructor() {
super();
}
private computeValue(): number {
return 42;
}
}
// ✅ CORRECT: Initialize in constructor after super()
class Derived extends Base {
private calculatedValue: number;
constructor() {
super();
this.calculatedValue = this.computeValue(); // Safe after super()
}
private computeValue(): number {
return 42;
}
}
// ✅ ALTERNATIVE: Use a static method if no instance needed
class Derived extends Base {
private calculatedValue = Derived.computeStaticValue();
constructor() {
super();
}
private static computeStaticValue(): number {
return 42;
}
}TypeScript parameter properties can't reference "this" before super():
// ❌ WRONG: Parameter property with "this" reference
class Derived extends Base {
constructor(private value = this.getDefault()) { // Error: "this" in default
super();
}
private getDefault(): string {
return 'default';
}
}
// ✅ CORRECT: Handle default values differently
class Derived extends Base {
private value: string;
constructor(value?: string) {
super();
this.value = value ?? this.getDefault(); // Safe after super()
}
private getDefault(): string {
return 'default';
}
}
// ✅ ALTERNATIVE: Use undefined check with default parameter
class Derived extends Base {
constructor(private value?: string) {
super();
if (this.value === undefined) {
this.value = this.getDefault();
}
}
private getDefault(): string {
return 'default';
}
}Methods or arrow functions that use "this" and are called before super() will fail:
// ❌ WRONG: Calling method that uses "this" before super()
class Derived extends Base {
constructor() {
this.initialize(); // Error: Method uses "this" internally
super();
}
private initialize(): void {
this.setup(); // Uses "this"
}
}
// ✅ CORRECT: Call methods after super()
class Derived extends Base {
constructor() {
super();
this.initialize(); // Safe after parent is initialized
}
private initialize(): void {
this.setup();
}
}
// ❌ WRONG: Arrow function in parameter default
class Derived extends Base {
constructor(callback = () => this.doSomething()) { // Error: "this" in arrow function
super();
}
}
// ✅ CORRECT: Handle callback initialization differently
class Derived extends Base {
private callback: () => void;
constructor(callback?: () => void) {
super();
this.callback = callback ?? (() => this.doSomething()); // Safe
}
}Ensure your TypeScript configuration handles class initialization correctly:
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"strictPropertyInitialization": true, // Catches uninitialized properties
"noImplicitThis": true, // Catches "this" with implicit 'any' type
"target": "es2015" // or higher for proper class support
}
}Key compiler options:
- strictPropertyInitialization: Ensures instance properties are initialized in constructor
- noImplicitThis: Error when "this" is implicitly 'any'
- useDefineForClassFields: Modern class field semantics (ES2022+)
Run tsc --noEmit to check for type errors after making changes.
Advanced notes
## Understanding JavaScript's Class Initialization Order
In JavaScript/TypeScript, class initialization follows this order:
1. Property initializers (ES2022 class fields) execute before the constructor
2. Constructor parameters are evaluated
3. super() must be called before accessing "this"
4. Remaining constructor body executes after super()
This is why property initializers can't use "this" - they run before the parent class is initialized.
## ES2022 Class Fields vs TypeScript's Implementation
TypeScript's class field behavior depends on the useDefineForClassFields compiler option:
- false (default for target < ES2022): Fields are initialized after super() in constructor
- true (ES2022+): Fields are initialized before constructor, following ES spec
With useDefineForClassFields: true, property initializers absolutely cannot use "this" since they run before the constructor.
## Abstract Classes and super()
For abstract classes, you still need to call super() even though there's no concrete parent:
abstract class Base {
abstract initialize(): void;
}
class Derived extends Base {
constructor() {
super(); // Still required for abstract classes
this.initialize();
}
initialize(): void {
// implementation
}
}## Mixins and Multiple Inheritance Patterns
When using mixins or similar patterns, ensure each mixin's initialization happens in the correct order:
function Timestamped<T extends new (...args: any[]) => any>(Base: T) {
return class extends Base {
timestamp = Date.now();
constructor(...args: any[]) {
super(...args); // Must call super() first
// mixin initialization
}
};
}## Performance Considerations
Calling super() early is not just a syntax requirement - it ensures proper memory layout and prototype chain setup. Accessing properties before the parent is initialized can lead to memory corruption or incorrect property lookups in optimized JavaScript engines.
Frequently asked questions
- What does "'super' must be called before accessing properties on 'this' in a deri" mean?
- The error "'super' must be called before accessing properties on 'this' in a derived class" is a fundamental JavaScript/TypeScript rule enforcement. In class-based inheritance, when you extend a parent class, the derived class's constructor must call super() before it can access the "this" keyword. This is because: 1.
- How do I fix "'super' must be called before accessing properties on 'this' in a deri"?
- This TypeScript/JavaScript error occurs when you try to access properties or methods using "this" in a derived class constructor before calling the parent class constructor with super(). The parent class must be initialized first before the derived class can safely use its own properties.
- What causes "'super' must be called before accessing properties on 'this' in a deri"?
- Accessing "this" keyword in derived class constructor before calling super() Trying to initialize derived class properties before parent class is ready Calling methods that use "this" before the parent constructor completes
- Is the "'super' must be called before accessing properties on 'this' in a deri" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖Typescriptlang.org - classes.html#super-calls(Official Docs)
- 🔗
- 🐙Github.com - 1617(GitHub)
- 💬Stackoverflow.com - javascript-es6-class-extend-without-super(Stack Overflow)
- 📖Typescriptlang.org - #useDefineForClassFields(Official Docs)