This TypeScript error occurs when you try to access a protected property from outside its class hierarchy. Protected members are only accessible within the class where they're defined and its subclasses, enforcing proper encapsulation.
TypeScript enforces access control through the protected modifier, which restricts property and method access to the class itself and any classes that inherit from it. When you attempt to access a protected member from outside this class hierarchy (such as from an external function, object instance, or sibling class), TypeScript throws a compilation error. This design prevents violation of encapsulation principles and ensures that internal implementation details remain hidden from external code while still allowing subclasses to access and extend base class functionality.
If you need to access the property from outside the class hierarchy, make it public:
class Animal {
// Change from protected to public
public species: string;
constructor(species: string) {
this.species = species;
}
}
const dog = new Animal('Canis familiaris');
console.log(dog.species); // ✓ Works - public propertyOnly make members public if they're part of the class's intended external interface.
Protected members are designed for use within the inheritance hierarchy:
class Vehicle {
protected speed: number = 0;
protected accelerate(amount: number): void {
this.speed += amount;
}
}
class Car extends Vehicle {
public drive(): void {
this.accelerate(10); // ✓ OK - accessing from subclass
console.log(`Speed: ${this.speed} mph`); // ✓ OK - accessing from subclass
}
}
const myCar = new Car();
myCar.drive(); // ✓ OK - calling public method
// myCar.speed; // ✗ Error - protected property
// myCar.accelerate(5); // ✗ Error - protected methodProvide controlled access to protected members through public methods:
class BankAccount {
protected balance: number = 0;
// Public getter provides read access
public getBalance(): number {
return this.balance;
}
// Public setter with validation
public deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
}
}
}
const account = new BankAccount();
account.deposit(100);
console.log(account.getBalance()); // ✓ Works: 100
// console.log(account.balance); // ✗ Error: protected propertyRefactor external code into methods within the class hierarchy:
class User {
protected email: string;
constructor(email: string) {
this.email = email;
}
// Internal method can access protected property
public sendNotification(message: string): void {
console.log(`Sending to ${this.email}: ${message}`);
}
}
class AdminUser extends User {
public updateEmail(newEmail: string): void {
this.email = newEmail; // ✓ OK - accessing from subclass
}
}
const admin = new AdminUser('[email protected]');
admin.sendNotification('Welcome!'); // ✓ OK
admin.updateEmail('[email protected]'); // ✓ OK
// console.log(admin.email); // ✗ ErrorProtected vs Private vs Public:
| Modifier | Same Class | Subclasses | Outside Class |
|----------|-----------|-----------|---------------|
| private | ✓ | ✗ | ✗ |
| protected | ✓ | ✓ | ✗ |
| public | ✓ | ✓ | ✓ |
Sibling class restriction:
TypeScript intentionally disallows accessing protected members of sibling classes (classes that extend the same base class but are not in a direct parent-child relationship). This is because even though both classes inherit from the same parent, they may have different implementations and accessing cross-instance protected members could violate encapsulation:
class Animal {
protected name: string = '';
}
class Dog extends Animal {
compareWith(other: Animal) {
// ✗ Error: Cannot access 'name' on type 'Animal'
// Even though Dog has access to its own 'name',
// 'other' might be a different subclass (Cat, Bird, etc.)
return this.name === other.name;
}
}Compile-time vs Runtime:
TypeScript's protected modifier is enforced only at compile time. After transpilation to JavaScript, protected members become regular properties accessible at runtime. For true runtime privacy, use ES2022 private fields (#) instead.
When to use protected:
Use protected when you want to:
- Share implementation details with subclasses
- Allow extension while hiding internals from external code
- Create template method patterns where base classes define protected hooks for subclasses to override
Avoid overusing protected modifiers as they create tight coupling between base and derived classes.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript