0
0
Typescriptprogramming~15 mins

Access modifiers public private protected in Typescript - Deep Dive

Choose your learning style9 modes available
Overview - Access modifiers public private protected
What is it?
Access modifiers in TypeScript are keywords that control how properties and methods of a class can be accessed. The three main modifiers are public, private, and protected. Public means anyone can access the member, private means only the class itself can access it, and protected means the class and its subclasses can access it. These modifiers help organize and protect data inside classes.
Why it matters
Without access modifiers, all parts of a program could freely change any data inside classes, which can cause bugs and make code hard to understand or maintain. Access modifiers help keep data safe and clear by limiting who can see or change it. This makes programs more reliable and easier to fix or improve over time.
Where it fits
Before learning access modifiers, you should understand basic classes and objects in TypeScript. After mastering access modifiers, you can learn about advanced object-oriented concepts like inheritance, encapsulation, and design patterns that rely on controlling access to class members.
Mental Model
Core Idea
Access modifiers are like gates that decide who can enter and use parts of a class.
Think of it like...
Imagine a house with rooms: public rooms are open to all guests, private rooms are locked and only the owner can enter, and protected rooms can be accessed by the owner and close family members.
Class Members Access
┌───────────────┐
│   public      │ ← Anyone can enter
├───────────────┤
│  protected    │ ← Owner + family (subclasses)
├───────────────┤
│   private     │ ← Owner only
└───────────────┘
Build-Up - 8 Steps
1
FoundationUnderstanding public access modifier
🤔
Concept: Public members are accessible from anywhere in the program.
In TypeScript, when you declare a class property or method as public, it means you can use it anywhere: inside the class, outside the class, or in other parts of your program. By default, members are public if no modifier is given. Example: class Car { public brand: string; constructor(brand: string) { this.brand = brand; } } const myCar = new Car('Toyota'); console.log(myCar.brand); // Works fine
Result
You can access and change public members from any code that has the class instance.
Knowing public means open access helps you decide when data or behavior should be freely available.
2
FoundationUnderstanding private access modifier
🤔
Concept: Private members are only accessible inside the class they belong to.
When you mark a property or method as private, only the class itself can use it. Trying to access it from outside the class causes an error. Example: class BankAccount { private balance: number; constructor(amount: number) { this.balance = amount; } getBalance() { return this.balance; } } const account = new BankAccount(1000); console.log(account.getBalance()); // 1000 // console.log(account.balance); // Error: balance is private
Result
Private members are hidden from outside code, protecting sensitive data.
Understanding private access helps you protect important data from accidental changes.
3
IntermediateExploring protected access modifier
🤔
Concept: Protected members are accessible inside the class and its subclasses.
Protected members act like private but allow subclasses to use them. This helps when you want to share data or behavior with child classes but keep it hidden from the outside. Example: class Animal { protected sound: string; constructor(sound: string) { this.sound = sound; } } class Dog extends Animal { makeSound() { return this.sound; } } const dog = new Dog('Bark'); console.log(dog.makeSound()); // Bark // console.log(dog.sound); // Error: sound is protected
Result
Protected members enable controlled sharing between parent and child classes.
Knowing protected lets you design flexible class hierarchies with safe data sharing.
4
IntermediateDefault access and explicit modifiers
🤔
Concept: Members without modifiers are public by default, but explicit modifiers improve clarity.
If you don't write any access modifier, TypeScript treats the member as public. However, writing public explicitly makes your code clearer and easier to understand. Example: class Person { name: string; // public by default public age: number; // explicitly public private ssn: string; constructor(name: string, age: number, ssn: string) { this.name = name; this.age = age; this.ssn = ssn; } }
Result
Explicit modifiers help readers quickly understand access rules.
Being explicit about access improves code readability and reduces mistakes.
5
IntermediateAccess modifiers with methods and properties
🤔
Concept: Access modifiers apply to both properties and methods, controlling their visibility.
You can use public, private, or protected on methods just like properties. This controls who can call those methods. Example: class Calculator { public add(a: number, b: number) { return a + b; } private log(result: number) { console.log('Result:', result); } calculate(a: number, b: number) { const sum = this.add(a, b); this.log(sum); return sum; } } const calc = new Calculator(); console.log(calc.add(2, 3)); // 5 // calc.log(5); // Error: log is private
Result
You control which methods are part of the class's public interface.
Controlling method access helps hide internal details and keep interfaces clean.
6
AdvancedAccess modifiers and inheritance rules
🤔Before reading on: Can private members be accessed by subclasses? Commit to yes or no.
Concept: Private members are not accessible by subclasses, but protected members are.
When a class inherits from another, it can use protected and public members of the parent, but not private ones. Private members belong only to the class that defines them. Example: class Parent { private secret = 'hidden'; protected shared = 'family'; } class Child extends Parent { reveal() { // console.log(this.secret); // Error: secret is private return this.shared; // Works } }
Result
Subclasses can use protected but not private members of their parents.
Understanding this prevents bugs when designing class hierarchies and access control.
7
AdvancedUsing access modifiers for encapsulation
🤔Before reading on: Does encapsulation mean hiding all data or controlling access? Commit to your answer.
Concept: Access modifiers help implement encapsulation by controlling what parts of a class are visible outside.
Encapsulation means bundling data and methods and hiding internal details. Using private and protected modifiers hides sensitive parts, exposing only what is needed. Example: class User { private password: string; constructor(password: string) { this.password = password; } checkPassword(input: string) { return input === this.password; } } const user = new User('1234'); // user.password; // Error: private console.log(user.checkPassword('1234')); // true
Result
Encapsulation improves security and reduces accidental misuse.
Knowing how access modifiers enforce encapsulation helps build robust, maintainable code.
8
ExpertTypeScript private vs JavaScript private fields
🤔Before reading on: Do TypeScript private members prevent access at runtime or only at compile time? Commit to your answer.
Concept: TypeScript private is a compile-time check, while JavaScript private fields (#) enforce privacy at runtime.
TypeScript's private keyword only stops access during development and compilation. At runtime, JavaScript does not enforce it, so private members can be accessed if you bypass TypeScript. JavaScript introduced private fields with # that are truly private at runtime. Example: class Example { private tsPrivate = 1; #jsPrivate = 2; } const e = new Example(); // e.tsPrivate; // Error in TypeScript // e.#jsPrivate; // Syntax error outside class // But at runtime, e['tsPrivate'] is accessible, while #jsPrivate is not.
Result
TypeScript private protects during coding, JavaScript private fields protect at runtime.
Knowing this difference helps avoid security mistakes and choose the right privacy level.
Under the Hood
TypeScript access modifiers are enforced by the compiler during development. They add metadata to class members to restrict access in the code editor and during compilation. However, the compiled JavaScript does not include these restrictions for public and private members, so access control is not enforced at runtime except for JavaScript private fields (#). Protected members are also a compile-time concept allowing subclass access. This means access modifiers help catch errors early but do not guarantee runtime security.
Why designed this way?
TypeScript was designed as a superset of JavaScript to add static typing and safety without changing runtime behavior. Enforcing access modifiers only at compile time allows compatibility with existing JavaScript code and engines. JavaScript later added private fields (#) for true runtime privacy, but TypeScript's approach balances safety and flexibility for developers.
TypeScript Class Member Access
┌───────────────┐
│  Source Code  │
│  class A {   │
│    private x;│
│    public y; │
│    protected z;│
└──────┬────────┘
       │ Compiler checks access
       ▼
┌───────────────┐
│ Compiled JS   │
│ function A(){}│
│ A.prototype.y │
│ A.prototype.x │ // accessible but discouraged
│ A.prototype.z │
└───────────────┘

JavaScript runtime does not enforce private/protected except for #private fields.
Myth Busters - 4 Common Misconceptions
Quick: Does TypeScript private guarantee runtime privacy? Commit to yes or no.
Common Belief:Private members in TypeScript are completely hidden and inaccessible at runtime.
Tap to reveal reality
Reality:TypeScript private only restricts access during development and compilation; at runtime, private members exist as normal properties and can be accessed if bypassed.
Why it matters:Assuming runtime privacy can lead to security risks or bugs when code accesses supposed private data.
Quick: Can subclasses access private members of their parent class? Commit to yes or no.
Common Belief:Subclasses can access private members of their parent class because they inherit everything.
Tap to reveal reality
Reality:Private members are only accessible inside the class that defines them; subclasses cannot access private members directly.
Why it matters:Misunderstanding this causes errors and confusion when designing class hierarchies.
Quick: Is protected the same as private? Commit to yes or no.
Common Belief:Protected members are just another name for private members.
Tap to reveal reality
Reality:Protected members are accessible to subclasses, unlike private members which are not.
Why it matters:Confusing these leads to incorrect access control and broken inheritance designs.
Quick: Are members without any modifier private by default? Commit to yes or no.
Common Belief:If you don't write public, private, or protected, members are private by default.
Tap to reveal reality
Reality:Members without modifiers are public by default in TypeScript.
Why it matters:Assuming default privacy can cause unexpected access and bugs.
Expert Zone
1
TypeScript's private modifier is a compile-time construct and can be bypassed using bracket notation or casting, so it should not be relied on for security.
2
Protected members allow subclasses to access and modify internal state, but overusing protected can break encapsulation and make code harder to maintain.
3
Using JavaScript private fields (#) alongside TypeScript access modifiers can provide true runtime privacy but requires understanding both systems and their limitations.
When NOT to use
Avoid using private or protected when you need to expose members for external libraries or frameworks that rely on reflection or dynamic access. Instead, use public with clear documentation or symbols for semi-private members. For true runtime privacy, prefer JavaScript private fields (#) or closures.
Production Patterns
In production, developers use private for sensitive data like passwords or internal counters, protected for extensible base classes, and public for APIs. They combine access modifiers with readonly and getters/setters to control mutation. Some use naming conventions (like underscore prefix) for soft privacy when interoperability is needed.
Connections
Encapsulation in Object-Oriented Programming
Access modifiers implement encapsulation by controlling visibility of class members.
Understanding access modifiers deepens your grasp of encapsulation, a core OOP principle that keeps data safe and interfaces clean.
Information Hiding in Software Engineering
Access modifiers are a practical tool for information hiding, limiting what parts of a system are visible to others.
Knowing how access modifiers enforce information hiding helps design modular, maintainable software systems.
Security Principles in Computer Science
Access control in programming languages parallels security controls that restrict access to resources.
Recognizing access modifiers as a form of access control connects programming to broader security concepts, emphasizing the importance of protecting data.
Common Pitfalls
#1Trying to access private members from outside the class.
Wrong approach:class Example { private secret = 42; } const e = new Example(); console.log(e.secret); // Error: secret is private
Correct approach:class Example { private secret = 42; getSecret() { return this.secret; } } const e = new Example(); console.log(e.getSecret()); // 42
Root cause:Misunderstanding that private members are only accessible inside their own class.
#2Assuming protected members are accessible outside subclasses.
Wrong approach:class Base { protected value = 10; } const b = new Base(); console.log(b.value); // Error: value is protected
Correct approach:class Base { protected value = 10; } class Derived extends Base { show() { return this.value; } } const d = new Derived(); console.log(d.show()); // 10
Root cause:Confusing protected access as public access.
#3Not using explicit access modifiers, causing confusion.
Wrong approach:class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } // All members are public but not obvious
Correct approach:class Person { public name: string; public age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } // Explicit public modifiers improve clarity
Root cause:Assuming default access is obvious to all readers.
Key Takeaways
Access modifiers control who can see and use class members, helping organize and protect code.
Public members are open to all, private members are hidden inside the class, and protected members are shared with subclasses.
TypeScript enforces access modifiers at compile time, but only JavaScript private fields (#) enforce privacy at runtime.
Using access modifiers properly supports encapsulation, making code safer and easier to maintain.
Misunderstanding access rules leads to bugs and design problems, so always be clear and explicit about access.