Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

In TypeScript, overriding a getter involves redefining a get accessor in a derived class that was originally declared as a getter or a property in a base class. By applying the override modifier, the TypeScript compiler enforces a structural check to guarantee that the member being overridden exists in the base class type.

Syntax and Implementation

To override a getter, declare a get accessor in the subclass with the exact same identifier as the base member, preceded by the override keyword.
class Base {
    get value(): number | string {
        return 0;
    }
}

class Derived extends Base {
    override get value(): number {
        return 42;
    }
}

Compiler Rules and Mechanics

Type Covariance The return type of the overridden getter must be assignable to the return type of the base getter. TypeScript enforces covariance for getters, meaning the derived getter can return a narrower (more specific) type, but not a wider type. In the example above, narrowing number | string to number is strictly valid. The override Modifier While technically optional by default, the override keyword becomes mandatory if the noImplicitOverride compiler option is enabled in tsconfig.json. When used, it prevents silent errors by throwing a compilation error if the base class member is renamed, removed, or has its signature changed. Property-to-Getter Overriding and Runtime Hazards TypeScript’s structural typing system allows a derived class to override a standard data property from a base class using a getter. However, overriding a class field with a getter introduces severe runtime hazards depending on the useDefineForClassFields compiler option (which defaults to true for ES2022+ targets):
  • If useDefineForClassFields is true, the base constructor defines the property directly on the instance using Object.defineProperty (or native class fields). Both initialized and uninitialized fields are emitted (with uninitialized fields explicitly set to undefined). This instance property silently shadows the getter defined on the derived class’s prototype.
  • If useDefineForClassFields is false, uninitialized fields are completely elided from the emitted JavaScript. Because no assignment occurs in the base constructor, the derived getter functions normally. However, initialized fields emit a standard assignment (e.g., this.config = "default"). Because the derived prototype defines a getter without a setter, this assignment throws a TypeError at runtime.
To safely override a property with a getter without runtime shadowing or errors, the base class property must not emit initialization code. This requires the base property to be abstract or declared using the declare keyword.
class BaseProperty {
    // 'declare' ensures no initialization code is emitted in the base constructor
    declare readonly config: string;
}

class DerivedGetter extends BaseProperty {
    override get config(): string {
        return "custom";
    }
}
Access Modifier Restrictions The visibility of the overridden getter must be equal to or more permissive than the base getter. A public base getter cannot be overridden by a protected or private getter, as this would violate the Liskov Substitution Principle. Setter Pairing If the base class defines both a get and a set accessor, overriding only the get accessor in the derived class does not automatically inherit the base setter. In TypeScript, accessors are paired; overriding one requires you to override the other if you want to maintain both read and write capabilities on the derived class. Otherwise, the property becomes read-only on the derived instance.
class BasePaired {
    get data(): string { return ""; }
    set data(val: string) { /* ... */ }
}

class DerivedPaired extends BasePaired {
    // This makes 'data' read-only in DerivedPaired
    // The base setter is shadowed and inaccessible
    override get data(): string { return "new"; }
}
Master TypeScript with Deep Grasping Methodology!Learn More