TypeScript Class Access Modifiers
Access modifiers are like privacy settings for class members, controlling what code can see them. Use `public` (default), `private` (class-only), and `protected` (class and subclasses) to enforce encapsulation.
WHY IT EXISTS Access modifiers exist to control the visibility of class members (properties and methods). This practice, called encapsulation, prevents external code from depending on internal implementation details. By hiding internals and exposing a clear public interface, you make classes easier to refactor and maintain without breaking dependent code.
THE MENTAL MODEL Think of access modifiers as setting permissions on a shared document. A public member is viewable and editable by anyone. A protected member is for you and your direct team (subclasses). A private member is for your eyes only (the class itself).
HOW IT WORKS TypeScript provides three access modifier keywords. If no modifier is specified, the member is public by default.
PUBLIC: Members are accessible from anywhere, both inside and outside the class. This is the default behavior.
PRIVATE: Members are only accessible from within the class in which they are declared. An instance of the class cannot access its own private members from the outside.
PROTECTED: Members are accessible within the declaring class and by any subclasses that extend it. They are not accessible from unrelated code.
A key distinction exists between TypeScript's private keyword and JavaScript's native #private syntax. TypeScript's private is a compile-time check only; it's erased during compilation, and the property can still be accessed at runtime. In contrast, #private fields are enforced by the JavaScript runtime, providing "hard" privacy.
WHEN TO USE IT Use public for the intended external API of your class—the methods and properties consumers of your class are meant to use. Use private for internal helper methods or state that should not be modified from the outside. Use protected when designing a class for inheritance, allowing subclasses to access and extend base functionality without exposing it publicly.
WHEN NOT TO USE IT Avoid making everything public, as this creates a brittle API where any change can be a breaking change. Don't overuse protected, as it can tightly couple a base class to its subclasses, making refactoring difficult. For true runtime privacy or security, do not rely on TypeScript's private keyword; use the ECMAScript #private syntax instead.
ONE CANONICAL EXAMPLE A Person class has a protected name, so it can't be accessed directly. An Employee class extends Person and can access name within its own methods because it's a subclass. An instance of Employee cannot have its name property accessed from the outside.
class Person { protected name: string; constructor(name: string) { this.name = name; } }
class Employee extends Person { public getElevatorPitch() { return My name is ${this.name}.; // OK to access 'name' here. } }
const emp = new Employee("Howard"); console.log(emp.getElevatorPitch()); // Prints "My name is Howard." // console.log(emp.name); // This would cause a compile-time error.
Read the original → typescriptlang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.