This TypeScript error occurs when the 'super' keyword is used incorrectly, typically outside of a class constructor or method, or in a context where it doesn't make sense. The fix involves ensuring 'super' is only used within class constructors to call parent constructors, or within class methods to call parent methods.
The "'super' keyword is unexpected here" error appears when TypeScript encounters the `super` keyword in an invalid context. The `super` keyword has specific rules in TypeScript/JavaScript: 1. **Constructor context**: In a class constructor, `super()` must be called before accessing `this` to initialize the parent class 2. **Method context**: In class methods, `super.methodName()` can be used to call parent class methods 3. **Property access**: `super.property` can access parent class properties This error typically occurs when: - Using `super` outside of a class entirely - Using `super` in a static method (where it doesn't make sense) - Using `super` in an arrow function inside a class (which doesn't have its own `super` binding) - Using `super` incorrectly in constructor logic TypeScript enforces these rules to ensure proper class inheritance and prevent runtime errors.
The super keyword can only be used inside class methods (including constructors). Check that you're not using it elsewhere:
// WRONG - using super outside a class
function someFunction() {
super.someMethod(); // Error: 'super' keyword is unexpected here
}
// CORRECT - using super inside a class method
class ChildClass extends ParentClass {
someMethod() {
super.someMethod(); // Valid: inside class method
}
}
// WRONG - using super in static method
class ChildClass extends ParentClass {
static staticMethod() {
super.staticMethod(); // Error: 'super' cannot be referenced in static initializers
}
}
// CORRECT - calling parent static method directly
class ChildClass extends ParentClass {
static staticMethod() {
ParentClass.staticMethod(); // Valid: reference parent class directly
}
}Move any super usage into proper class methods.
Arrow functions don't have their own super binding. Use regular function syntax instead:
class ParentClass {
parentMethod() {
return "parent";
}
}
class ChildClass extends ParentClass {
// WRONG - arrow function doesn't have super
childMethod = () => {
super.parentMethod(); // Error: 'super' keyword is unexpected here
};
// CORRECT - use regular method syntax
childMethod() {
super.parentMethod(); // Valid
}
// ALTERNATIVE - bind arrow function to access parent method
childMethod = () => {
ParentClass.prototype.parentMethod.call(this); // Access parent method directly
};
}For class properties that need to reference parent methods, consider:
1. Using regular method syntax
2. Calling the parent method directly via ParentClass.prototype.methodName.call(this)
3. Storing a reference to the parent method in the constructor
If you're extending a class, you must call super() in the constructor before using this:
class ParentClass {
constructor(public name: string) {}
}
class ChildClass extends ParentClass {
// WRONG - missing super() call
constructor(name: string, public age: number) {
this.age = age; // Error: 'super' must be called before accessing 'this'
}
// CORRECT - call super() first
constructor(name: string, public age: number) {
super(name); // Must be called first
this.age = age; // Now valid
}
// WRONG - super() called after this
constructor(name: string, public age: number) {
this.age = age; // Error: 'super' must be called first
super(name);
}
}The order matters:
1. super(...args) must be the first statement in derived class constructors
2. Only after super() can you use this
3. If the parent class has no constructor, still call super() with no arguments
super only works in classes, not in object literals or other contexts:
// WRONG - using super in object literal
const obj = {
method() {
super.toString(); // Error: 'super' keyword is unexpected here
}
};
// CORRECT - use classes instead
class MyClass {
method() {
super.toString(); // Valid if MyClass extends something
}
}
// WRONG - using super as a variable name
const super = "something"; // Error: 'super' is a reserved word
// CORRECT - use different variable name
const parentRef = "something";
// WRONG - trying to access super properties incorrectly
class ChildClass extends ParentClass {
method() {
const prop = super; // Error: 'super' can only be used to call methods
prop.someMethod(); // This won't work
}
}
// CORRECT - call super methods directly
class ChildClass extends ParentClass {
method() {
super.someMethod(); // Valid
}
}Remember: super is not a reference to the parent class instance; it's a special keyword for calling parent methods/constructors.
Ensure your class actually extends another class when using super:
// WRONG - class doesn't extend anything
class StandaloneClass {
constructor() {
super(); // Error: 'super' keyword is unexpected here
}
}
// CORRECT - only use super when extending
class ChildClass extends ParentClass {
constructor() {
super(); // Valid
}
}
// Check your imports and class definitions
import { ParentClass } from "./ParentClass";
// Ensure the parent class is properly defined
class ParentClass {
// ... implementation
}
class ChildClass extends ParentClass {
// Now super will work
constructor() {
super();
}
}If you're not extending a class, you don't need super. For standalone classes, remove the super() call from the constructor.
When overriding parent class methods, use super to call the parent implementation:
class ParentClass {
logMessage(message: string) {
console.log("Parent: " + message);
}
}
class ChildClass extends ParentClass {
// CORRECT - override and call parent method
logMessage(message: string) {
super.logMessage(message); // Call parent implementation
console.log("Child: " + message); // Add child behavior
}
// WRONG - incorrect super usage in non-override
someNewMethod() {
super.nonExistentMethod(); // Error if parent doesn't have this method
}
// CORRECT - check if method exists
someNewMethod() {
if (super.logMessage) {
super.logMessage("calling from new method");
}
}
}Key points:
1. Only use super.methodName() when methodName exists in the parent class
2. super gives access to parent class methods, not properties (use this.property for inherited properties)
3. You can call super multiple times in a method if needed
### Understanding super in JavaScript/TypeScript
The super keyword behaves differently in various contexts:
In constructors:
- super(args) calls the parent class constructor
- Must be called before accessing this
- If omitted, TypeScript will automatically insert super() for you (calling the parent's default constructor)
In methods:
- super.methodName(args) calls the parent class's method
- The super reference is bound to the current instance (this)
- You can use super to access parent methods that you're overriding
In property accessors (getters/setters):
class ParentClass {
private _value = 0;
get value() { return this._value; }
set value(v) { this._value = v; }
}
class ChildClass extends ParentClass {
get value() {
return super.value * 2; // Access parent getter
}
set value(v) {
super.value = v / 2; // Access parent setter
}
}### super and Prototype Chain
Under the hood, super.method() roughly translates to:
// super.method() is similar to:
Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this);This is why arrow functions don't have super - they don't have their own this binding, so they can't traverse the prototype chain correctly.
### Static Methods and super
Static methods cannot use super because they're called on the class itself, not instances. Instead, reference the parent class directly:
class ParentClass {
static staticMethod() { return "parent"; }
}
class ChildClass extends ParentClass {
static staticMethod() {
// WRONG: super.staticMethod(); // Error
// CORRECT:
return ParentClass.staticMethod() + " child";
}
}### super in Mixins and Multiple Inheritance
TypeScript doesn't support multiple inheritance, but you can use mixins. With mixins, super refers to the next class in the prototype chain:
type Constructor<T = {}> = new (...args: any[]) => T;
function Timestamped<TBase extends Constructor>(Base: TBase) {
return class extends Base {
timestamp = Date.now();
log() {
super.log?.(); // Call parent log if it exists
console.log(this.timestamp);
}
};
}
class BaseClass {
log() { console.log("base"); }
}
const TimestampedClass = Timestamped(BaseClass);
const instance = new TimestampedClass();
instance.log(); // Outputs: "base" then timestamp### Common Pitfalls
1. Async methods: super works fine in async methods
2. Generators: super works in generator methods
3. Private fields: Cannot access parent private fields via super (they're not inherited)
4. Abstract classes: Must call super() in concrete class constructors extending abstract classes
### Debugging super Issues
Use console logging to understand what super refers to:
class ChildClass extends ParentClass {
debugSuper() {
console.log(super.constructor); // Shows ParentClass constructor
console.log(Object.getPrototypeOf(this)); // Shows ChildClass prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(this))); // Shows ParentClass prototype
}
}Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript