-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow access to protected class members if the 'this' type of an (extension) function is specified #10302
Comments
thumb down: this undermines the purpose of |
@Aleksey-Bykov If your current function has access using As another point: There is also an escape hatch for type casting in TypeScript by casting something to So yeah: I personally consider every function whose |
why do we need what you are suggesting is that any 3rd party code can inject some logic into your class and feel like home there
|
Well first of all that's already possible since
Just take my use case: I have 2 classes for a certain parser. One of the central classes is about 4000 LOC. What I did is to split up the class in a "core" and multiple cleanly seperated extensions, but now I've got the problem that all members have to be public, or otherwise I can't access them without |
so what? are you suggesting to legalize a hack (accessing a member which is not supposed to be accessed) the fact that you still can do it from JavaScript is that TypeScript is ahead of what's coming next in ES2016, 2017 or whatever if the class is your own - you have it all you don't need this hack
i hear that you have problems with the size of your class, you options as always are:
|
// composition
interface PrivateMatters { x: number }
class A {
constructor(
private state: PrivateMatters
) {
this.b = new B(this.state);
this.c = new C();
}
public doThis() {
this.b.doThat(); // state is already in B
this.c.doThis(this.state);
}
}
// ioc
class A {
constructor(
private state: PrivateMatters
) {
}
public legallyUsingPrivateState<r>(extension: (x: number) => r): r {
return extension(this.state.x);
}
} |
It's not a hack because it would imply that you can do something that you couldn't do before. And yes I'm advocating for this obviously or why should I have created the issue then?
Would you be more comfortable with the proposal if I'd edit the title to read
Your Is it really so surreal to consider that there might be classes larger than a dozen LOC? Being able to split those up is one of the major benefits of extensions. |
it is a hack, because you cannot access a private member from outside of a class without waiving typechecking which is what TypeScript is for yes, protecteds would be a better fit for your proposal it's not bad as long as you
public legallyUsingPrivateState(extension: (x: number) => number): void {
const result = extension(this.state.x); // be aware of my private x if you can't help it
if (result > 0) { // let me check what you want to write back
this.state.x = result;
}
} not being able to decompose a 4000 LOC class into smaller classes is a bad sign that your code is overlycoupled, you need to reconsider the design |
The discussion right now is seriously drifting away from the original issue, which makes this my last comment about this.
You forgot about the member functions.
What? Should I special-case every single access? The code size just doubled for no apparent reason. Or should I do the FP way, make the state object immutable and return a new one from the extension to diff it with the previous one? While that would certainly solve it I don't see how that would make it any better. Oh and runtime cost: It's a parser. Those have to fast. Deep comparisons and/or modification bookkeeping? Not fast.
Just a minor nitpick: There are about 50 different packet types in my case and they all belong to the parser class. Even if you make a rough estimate and divide Anyways: You can't just split up some things into multiple classes without causing either a serious overhead, increased complexity, increased code size, and/or violation of some core principles like DRY. In fact I'd argue that my code is as little coupled as possible because every sub-parser is only depending on the core and on nothing else. What you probably suggest is that I should do some form of indirection between the "core" and the parts (like IoC using a seperate state object), which just doesn't solve the general problem at hand of having the capability to extend a class in a dynamic way, since this is a dynamic language. I'm interested if you can come up with a software pattern that doesn't require the main class to be wrapped for access control (which is pointless for a user-facing class, in a language which gets compiled to JS anyways), doesn't sacrifice performance and allows me to keep my code DRY in a situation where the main class is composited out of a large number of classes with shared state. Don't go around assuming that others don't know their craft. |
you can extend your class in a dynamic way as much as you want provided you do it via:
there are languages like C# and Java where hacking it to the private state (although still possible) is a hands down bad practice no questions asked, and nevertheless people are still able to craft decent parsers without running into problems like yours i cannot give you a better advice without looking at the code bottom line, even if everything you said is true and there is simply no way better to do it, it's not a reason for a feature that everyone else can live without, bad luck |
Allowing access to |
@RyanCavanaugh Yup I edited the title and example already. I really agree that |
👍 : treat functions annotated |
First of all: Please excuse me if this issue is a duplicate of some sort, but I've searched for quite some time for a similar issue or at least an answer to the following question/bug/proposal and found nothing.
If I specify that a function has a certain (customized) 'this' type I expect that the function has full access to protected or even private fields of passed instances. Reason being that due to JavaScripts dynamic nature and it's capability to overwrite the
this
pointer, a function that is freestanding can still act like an extension method to a class.Below you can find a simple JavaScript-like style of extending a existing class, which fails in TypeScript, because it strictly forbids access to private and protected fields outside of the actual class:
I realize that some kind of "official" class extension technique will get into TypeScript sooner or later, but all of the proposals I've seen extend the actual JavaScript language with new keywords. This question/bug/proposal here though, basically does exactly the same as the existing extension proposals but within the boundaries of the JavaScript language (apart from the existing language extensions for the type checker).
I thus humbly suggest to loosen this strict access control and allow us to write extension methods to at least some extend before v2.0 is finally released.
The text was updated successfully, but these errors were encountered: