The highly anticipated arrival of the protected access modifier is near. The protected keyword is similar to the implementation of protected in Java and C# – but as always, there are some interesting details – because TypeScript is structural, not nominal.
- Private members are only accessible within their declaring class.
- Protected members are only accessible within their declaring class and classes derived from it.
- Public members can be accessed anywhere.
When you override a private or protected member, you have to apply the same access level.
class MyClass { private privateProperty: string; protected protectedProperty: string; } class MySubClass extends MyClass { notAllowed() { return this.privateProperty; } thisIsAllowed() { return this.protectedProperty; } }
You can also access the protected property in the following situation.
class MyClass { private privateProperty: string; protected protectedProperty: string; } class MySubClass extends MyClass { static compare(a: MyClass, b: MySubClass) { // Accessing MyClass properties var notAllowed1 = a.privateProperty; var notAllowed2 = a.protectedProperty; // Accessing MySubClass properties var notAllowed3 = b.privateProperty; var allowed = b.protectedProperty; } }
Interesting note: In the above example, the static method on MySubClass accepts arguments of type MyClass and MySubClass – it is able to access the protected property on the instance of MySubClass (but not on MyClass).
Both private and protected members affect type matching in TypeScript: Private members only ever match themselves (i.e. the same private member from the same class). Protected members match themselves and overridden versions of themselves on sub-classes.
The protected keyword, just like the existing private keyword, can only be used within a class – not on an interface. If an interface inherits protected properties (remember, you can inherit from a class with your interface), then it can’t declare properties with the same name.
The final point to bear in mind is that the protected keyword is a compile-time constraint. You can use it to indicate intent, but not to enforce the rules at runtime.