Repository navigation
Different access modifier for getter and setter #2845
Description
Activity
- addedDuplicateAn existing issue was already createdAn existing issue was already created
on Apr 21, 2015 RyanCavanaugh commented
on Apr 21, 2015 MemberMore actions- Reacted by Luke Tanner, kanatkubash, Adem Aydin, Adam Pasternack, David Warburton, Bruno Schäpper, David Canning, Lawrence Bethlenfalvy, Joao Grassi, Thomas Hudson and 2 more
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensusand removedDuplicateAn existing issue was already createdAn existing issue was already created
on Jan 28, 2016 I believe I should also move my example here from related issue:
declare abstract class Emitter { new (): Emitter; on: (name:string, handler: (arg:any) => void) => void; off: (name:string, handler: (arg:any) => void) => void; protected emit: (name:string, arg:any) => void; } class Person extends Emitter { constructor(name:string) { super(); this.name = name; } private _name:string; get name() { return this._name; } set name(value) { if (this._name !== value) { this._name = value; this.emit('change:name', value); //this way is better this.updatedAt = new Date(); //than this way this.setUpdatedAt(new Date()); } } //// private _updatedAt:Date; get updatedAt() { return this._updatedAt; } private set updatedAt(value) { //Getter and setter do not agree in visibility //some logic and a simple readonly (our absence of a setter) is not enough if (this._updatedAt !== value) { this._updatedAt = value; this.emit('change:updatedAt', value); } } //// method implementation - but what's the point in it? private setUpdatedAt(value) { if (this._updatedAt !== value) { this._updatedAt = value; this.emit('change:updatedAt', value); } } } const entity = new Person('Mike'); entity.on('change:updatedAt', console.log.bind(console)); entity.name = 'Thomas'; //but manually setting updatedAt should be forbidden entity.updatedAt = new Date(); //restricted
Here, property
updatedAtactually can have a setter but it should not be accessable outside ofPerson. Moreover this setter contains complex logic and a simple readonly or an absence of a setter is not enough.I agree that private setter is just a syntax sugar for private methods with additional logic (like emitting) but I think it is inconsistent when part of logic related to a field is in a property (getter) and another in a method (private setter).
This way getters/setters are implemented in
C#, I think it would be usefull to allow different visibility at compile time, though this contracts will be lost in runtime.Reacted by Patricio Ezequiel Hondagneu Roig and Salvatore Previti- 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 Jan 29, 2016 The recommendation here is to use a public readonly getter and a private/protected backing field.
Accessors are symetrical with properties in the type system. anything we do will need to be manifested in the type and expressible on properties. Adding new access modifiers to enable private_set/public_get would increase the complexity of the language and the learning curve, and the value gained from this would not match the added complexity.
Reacted by Aluan HaddadReacted by Viktor Nikolaev, Timur Popov, Wilfred van der Deijl, Ben305, Will Wong (╯°□°)╯ ︵ ┻━┻, Joel, Bryson Thill, Eric Parsons, Mauricio Jorge Cordeiro Garrido, Meirion Hughes and 134 moreReacted by Pavel Botvinkin, Thomas Hudson, dark and KevinReacted by Trent Millar, Rodney S. Foley and Thomas Hudson- addedToo ComplexAn issue which adding support for may be too complex for the value it addsAn issue which adding support for may be too complex for the value it adds
on Jan 29, 2016 Anyway adding my +1 for this, in case it is considered again in future...
Reacted by Adam Keenan, Wilfred van der Deijl, Will Wong (╯°□°)╯ ︵ ┻━┻, AppLover69, Seivan, Artur Ampilogov, Bryson Thill, Fennec Cooper, Eric Parsons, Mauricio Jorge Cordeiro Garrido and 104 more32 remaining items
Type errors like the following are easy to understand and are not complicated:
Property 'foo' is writable only in protected scope within class 'Blah' and its subclasses.or
Property 'foo' is readable only in protected scope within class 'Blah' and its subclasses.etc, and similar with
private.That's honestly not complicated.
Reacted by Thomas Hudson and Gabriele TomberliBTW, I stumbled over this problem too, and I am using this kind of "hack" in the meantime:
// somewhere.ts declare global { type Writable<T> = { -readonly [P in keyof T]: T[P]; } } // example.ts class Example { public readonly prop: number; public doSomething(n: number): void { (this as Writable<this>).prop = n; } }
Technically, this could be used everywhere, but using this workaround should be restricted to code inside class methods.
Reacted by TotatiBTW, I stumbled over this problem too, and I am using this kind of "hack" in the meantime:
I've played with this idea myself, but the problem is you have no way to distinguish between "public read-only" and truly read-only properties. This makes it not very suitable as a general-purpose solution.
Reacted by Shawn Dotey and ExE Boss- addedIn DiscussionNot yet reached consensusNot yet reached consensusand removedDeclinedThe issue was declined as something which matches the TypeScript visionThe issue was declined as something which matches the TypeScript visionToo ComplexAn issue which adding support for may be too complex for the value it addsAn issue which adding support for may be too complex for the value it adds
on Feb 3, 2021 - added a commit that references this issue
on Mar 24, 2021 RyanCavanaugh commented
on Mar 25, 2021 MemberMore actionsThere's a Playground build for PR 42425 available for trying out and I'd appreciate any feedback on how it meets folks' needs here. Thanks! See comments in #42425 on how this works.
Reacted by Koloto, Shinigami, ExE Boss, Thomas Hudson, Gabriele Tomberli, btoo, Kevin Ralphs, Nerlin~ and StuckDuckReacted by csha and StuckDuckThis is nice. I hope it's a step toward asymmetric accessibility of data properties.
This is great to see. Apologies my prior comment was directed to the disnissive way this issue was summarily closed by the former team manager years ago. Ryan Cavanaugh (@RyanCavanaugh) I'm glad to see typescript gaining more parity with languages like C#. Great work.
The recommendation here is to use a public readonly getter and a private/protected backing field.
Accessors are symetrical with properties in the type system. anything we do will need to be manifested in the type and expressible on properties. Adding new access modifiers to enable private_set/public_get would increase the complexity of the language and the learning curve, and the value gained from this would not match the added complexity.
I am sorry but this is a rubbish reason. Typescript includes features like private constructors, yet you say that the complexity of different getters/setters is too high and steepens the learning curve. Like somebody mentioned here,
it is hard to makeshould not be an argument against a standard in most modern programming languages. Your suggestion to use private/protected is not really helpful either - it makes the code less readable and it adds complexity to it.Reacted by Rémi VansteelandtReacted by Gabriele Tomberli, Alexander, Kun R and Mike RipponI am sorry but this is a rubbish reason. Typescript includes features like private constructors, yet you say that the complexity of different getters/setters is too high and steepens the learning curve. Like somebody mentioned here, it is hard to make should not be an argument against a standard in most modern programming languages. Your suggestion to use private/protected is not really helpful either - it makes the code less readable and it adds complexity to it.
You might want to consider reading more than the first few comments. The one you quoted was written over 5 years ago, several months before even the addition of private constructors (TypeScript 2.0) you're talking about.
TypeScript has gone a long way since then, see the comments and linked commit (which landed in 4.3) right above.Leo Friedrichs (@RiftLurker) I know that, but that does not change the point. I did read the thread, and I do know the changes are in 4.3.
Reacted by Kirill Agalakov, Gabriele Tomberli, Kun R, Benjamin Duncan and Mike Rippon
Could it be possible to implement different access modifier for getter and setter? This way the setter could be for example private/protected and the getter public. In some cases this in really useful when the value shall be read-only.
Example: