Repository navigation
Allow interfaces to declare protected members and allow implementors to implement protected and private members. #3854
Description
Activity
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensus
on Aug 10, 2015 This is a wider issue as it also applies to optional status. See Rules for intersection types are inconsistent with rules for implementing multiple interfaces. #4278
Perhaps this issue should be closed as a duplicate of #4278.
There is a workaround for this (at least in 1.6, I haven't tried earlier versions):
Given these classes:interface A { a; } class B implements A { protected _a; get a() { return this._a; } BFunc() { }; } class C implements A { protected _a; get a() { return this._a; } CFunc() { }; }
To create a class implementing both
BandCwe can inherit from one and implement the other. Implementing an interface with a protected member is an error, but relaxing the protection in a derived class is not.class B_public extends B { public _a;} class C_public extends C { public _a;} class D extends B_public implements C_public { CFunc() { }; }
Note that this workaround above does not work for
privatemembers. see #471 which is currentlyNeedsProposalfor a proposal which would allow the workaround to succeed.Still waiting :)
DanielRosenwasser commented
on Aug 4, 2016 MemberMore actionsMateusz Paluszkiewicz (@TheAifam5) we are currently working through 2.0 and handling other tasks, with others not in the office. Sorry for any delays.
Sooo ??? How are things going :)
What's the current point of view on this feature?
Looking at this again, i do not see how this can be done in a safe manner. a private member specifically can not match any other declaration other than itself, otherwise there are no guarantees whatsoever about type safety in the class declaring it (keep in mind that ambient classes do not have types for their private members).
- addedDeclinedThe issue was declined as something which matches the TypeScript visionThe issue was declined as something which matches the TypeScript visionand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Dec 1, 2017 - locked and limited conversation to collaborators
on Jun 19, 2018
TL;DR: provide a syntax which kills this compiler error:
If the implementer wants to take responsibility for making sure the private members behave correctly they should be able to do so.
This would allow mixins to have protected members and solve a few issues with other multiple inheritance use-cases.
Proposal: Allow implementation of protected and private members in derived and implementing classes
Allow interface implementers to implement protected and private methods. This makes it possible for types with private and protected members to be implemented as interfaces (provided the inheritor correctly manages the private state).
Suggested syntax:
Since name mangling is not used we can't alias the private members, so if implementing more than one interface with private members, the private members must either have different names, or the underlying uses of the members must be compatible, or be made compatible.
Of course interfaces can have protected and private members, though they can't declare them directly and you can't implement them directly:
I understand the explanation given in #471, that we cannot simply ignore the private members, as e.g. other instances of B need to be able to access B's private members on C. However protected members are part of the API contract too, for inheritors, and we should be able to implement them.
What's more, nothing is truly private in JavaScript. This can be achieved in typescript using the
["_p"]escape hatch and an intermediate class as above.Motivation
Several uses for this. One is that it seems to be the only way to allow mixins to have private or protected members.
I'm working with a large library, and have come across the following situation, where I need a type which implements two classes/interfaces which derive from a common base.
Given these classes:
I need then to create a class implementing both
BandC. Note that bothBandChave chosen to implementausing a protected backing member_a, and that these are compatible implementations with exactly the same meaning. There is now no way to achieve this.Allowing interfaces to declare protected members would make them part of the API contract for inheritors and would solve this problem.
This does not work:
Neither does this:
For example if I could reopen the interface like so:
That would solve the issue. By declaring it part of the API contract, albeit one only accessible to inheritors, we solve the problem.
Currently the only way to work around involves making the backing member public in the interface, or public in the derived classes. (There has to be a backing member in this case). Even making the
Aa class, and declaring the protected member won't allow you to do it.