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.

A private method in TypeScript is a class member function restricted to the lexical scope of its declaring class. It cannot be invoked on class instances from outside the class, nor can it be accessed by derived subclasses or external modules. It can, however, be invoked on instances (e.g., this.formatData() or otherInstance.formatData()) provided the invocation occurs strictly within the declaring class’s body. TypeScript provides two distinct syntactical mechanisms for implementing method privacy: the TypeScript-specific private access modifier and the ECMAScript standard # (hash) prefix.

The private Access Modifier (Compile-Time Privacy)

The private keyword is a TypeScript-specific access modifier. It enforces encapsulation strictly during the static type-checking phase.
class LegacyProcessor {
  private formatData(input: string): string {
    return input.trim().toLowerCase();
  }

  public process(input: string): void {
    // Valid: Invoked within the declaring class's lexical scope
    const formatted = this.formatData(input);
  }
}

const processor = new LegacyProcessor();
// TypeScript Error: Property 'formatData' is private and only accessible within class 'LegacyProcessor'.
processor.formatData("  Data  "); 
Technical Characteristics:
  • Type Erasure: The private keyword is stripped during transpilation. In the emitted JavaScript, the method becomes a standard, publicly accessible prototype method.
  • Compile-Time Bypass: Because privacy is only enforced by the static type checker, the restriction can be bypassed at compile-time by casting the instance to any (e.g., (processor as any).formatData("...")). Note that in modern TypeScript (v4.1+), attempting to bypass the type checker using bracket notation (e.g., processor['formatData']("...")) produces a strict compile-time error.

The # Prefix (Runtime Privacy)

The # prefix implements ECMAScript private class features. Unlike the private keyword, this provides hard privacy enforced by the JavaScript engine at runtime.
class ModernProcessor {
  #formatData(input: string): string {
    return input.trim().toLowerCase();
  }

  public process(input: string): void {
    // Valid: Invoked within the declaring class
    const formatted = this.#formatData(input);
  }
}

const processor = new ModernProcessor();
// TypeScript Error: Property '#formatData' is not accessible outside class 'ModernProcessor' because it has a private identifier.
processor.#formatData("  Data  ");
Technical Characteristics:
  • Runtime Enforcement: The method remains strictly inaccessible outside the class boundary at runtime. It cannot be bypassed using type casting, as the underlying JavaScript engine enforces the boundary.
  • Emission: Depending on the target specified in tsconfig.json, TypeScript will either emit native ECMAScript private methods (for ES2022+) or downlevel the code. When downleveling private methods, TypeScript utilizes WeakSet implementations to verify instance membership alongside module-scoped functions (unlike private fields, which are downleveled using WeakMap).
  • Identifier Resolution: The # is inherently part of the method’s name. A class can possess both a public method and a private # method with the same base identifier (e.g., formatData() and #formatData()) without collision.

Inheritance Behavior

Neither mechanism allows method access within derived classes. Attempting to invoke a private method from a subclass results in a static type error.
class BaseClass {
  private tsPrivate(): void {}
  #esPrivate(): void {}
}

class DerivedClass extends BaseClass {
  public testAccess(): void {
    // Error: Property 'tsPrivate' is private and only accessible within class 'BaseClass'.
    this.tsPrivate(); 
    
    // Error: Property '#esPrivate' is not accessible outside class 'BaseClass' because it has a private identifier.
    this.#esPrivate(); 
  }
}
If a method must be accessible to subclasses while remaining hidden from external consumers, the protected modifier must be used instead of private or #.
Master TypeScript with Deep Grasping Methodology!Learn More