Understanding TypeScript Access Modifiers: A Beginner’s Guide

Access modifiers are a fundamental concept in TypeScript that help you control the visibility and accessibility of class members. Whether you’re new to TypeScript or looking to deepen your understanding, this guide will walk you through everything you need to know about TypeScript access modifiers.

Table of Contents

What Are Access Modifiers?

Access modifiers are keywords that set the accessibility scope of class members (properties and methods). TypeScript provides three access modifiers:

  • public
  • private
  • protected

The Public Modifier

The public modifier is TypeScript’s default access level. When a class member is marked as public, it can be accessed from anywhere.

class Employee {
  public name: string;

  constructor(name: string) {
    this.name = name;
  }

  public displayName(): void {
    console.log(this.name);
  }
}

const employee = new Employee("John Doe");
console.log(employee.name); // Accessible
employee.displayName(); // Accessible
Code language: JavaScript (javascript)

The Private Modifier

When you mark a class member as private, it can only be accessed within the class where it’s declared.

class BankAccount {
  private balance: number;

  constructor(initialBalance: number) {
    this.balance = initialBalance;
  }

  public getBalance(): number {
    return this.balance;
  }

  private updateBalance(amount: number): void {
    this.balance += amount;
  }

  public deposit(amount: number): void {
    this.updateBalance(amount);
  }
}

const account = new BankAccount(1000);
// account.balance; // Error: 'balance' is private
// account.updateBalance(500); // Error: 'updateBalance' is private
account.deposit(500); // Works fine
Code language: JavaScript (javascript)

The Protected Modifier

The protected modifier allows access within the declaring class and any classes that inherit from it.

class Animal {
  protected species: string;

  constructor(species: string) {
    this.species = species;
  }

  protected makeSound(): void {
    console.log("Some generic sound");
  }
}

class Dog extends Animal {
  public bark(): void {
    console.log(`${this.species} says: Woof!`);
    this.makeSound(); // Accessible because it's protected
  }
}

const dog = new Dog("Canine");
// dog.species; // Error: 'species' is protected
dog.bark(); // Works fine
Code language: JavaScript (javascript)

Parameter Properties Shorthand

TypeScript provides a convenient shorthand for declaring and initializing class members in the constructor using access modifiers:

class User {
  constructor(
    public username: string,
    private password: string,
    protected email: string
  ) {}

  public displayInfo(): void {
    console.log(`Username: ${this.username}`);
    // We can access private and protected members here
    console.log(`Password: ${this.password}`);
    console.log(`Email: ${this.email}`);
  }
}
Code language: JavaScript (javascript)

Best Practices

  1. Default to Private: Start by making class members private and only make them more accessible when needed.

  2. Use Protected for Inheritance: When you need to share functionality between parent and child classes, use protected instead of public.

  3. Encapsulation: Use private members with public methods to control how class state is modified:

class Counter {
  private count: number = 0;

  public increment(): void {
    this.count++;
  }

  public getCount(): number {
    return this.count;
  }
}
Code language: JavaScript (javascript)
  1. Documentation: Always document public APIs that other developers will use:
/** 
 * Represents a user in the system.
 */
class User {
  /**
   * Creates a new user.
   * @param username The user's display name
   */
  constructor(public username: string) {}
}
Code language: PHP (php)

Common Gotchas and Solutions

Runtime vs. Compile Time

Remember that access modifiers are a TypeScript feature and are removed during compilation to JavaScript. They provide compile-time checks only:

class Example {
  private secret: string = "hidden";
}

// In compiled JavaScript, the private member is still accessible
// const example = new Example();
// console.log(example["secret"]); // Would work in JavaScript!
Code language: PHP (php)

Private Fields in JavaScript

For true runtime privacy, consider using JavaScript’s private fields with the # prefix:

class Modern {
  #truePrivate = "can't access this at runtime";

  public accessPrivate(): string {
    return this.#truePrivate;
  }
}
Code language: PHP (php)

Conclusion

Mastering TypeScript access modifiers is crucial for writing maintainable and secure code. They help you implement proper encapsulation and create clear boundaries in your codebase. Start applying these concepts in your TypeScript projects, and you’ll see immediate benefits in code organization and maintainability.

For more advanced TypeScript features, check out our guide on TypeScript Type Guards or explore TypeScript Interfaces for better type definitions.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share via
Copy link
Powered by Social Snap