Skip to content

Different access modifier for getter and setter #2845

Description

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:

class MyClass {
    private _myProp: any;
    private set myProp(value: any) {
        this._myProp = value;
    }
    public get myProp(): any {
        return this._myProp;
    }
}

Activity

  1. RyanCavanaugh commented on Apr 21, 2015

    @RyanCavanaugh
    Member
  2. raveclassic commented on Jan 28, 2016

    @raveclassic

    As #12 is closed with #6532 now it seems that this issue is out of scope.
    Do you now have any plans on implementing different access modifiers?
    Because readonly is not enough to solve what's described here as a property might be actually writable inside a class.

  3. raveclassic commented on Jan 28, 2016

    @raveclassic

    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 updatedAt actually can have a setter but it should not be accessable outside of Person. 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.

  4. added
    DeclinedThe issue was declined as something which matches the TypeScript vision
    and removed on Jan 29, 2016
  5. mhegazy commented on Jan 29, 2016

    @mhegazy
    Contributor

    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.

  6. 0815fox commented on Jun 22, 2016

    @0815fox

    Anyway adding my +1 for this, in case it is considered again in future...

  7. 32 remaining items

  8. trusktr commented on Nov 18, 2020

    @trusktr
    Contributor

    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.

  9. danielrentz commented on Dec 4, 2020

    @danielrentz

    BTW, 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.

  10. snarfblam commented on Dec 5, 2020

    @snarfblam

    BTW, 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.

  11. added and removed
    DeclinedThe issue was declined as something which matches the TypeScript vision
    Too ComplexAn issue which adding support for may be too complex for the value it adds
    on Feb 3, 2021
  12. added a commit that references this issue on Mar 24, 2021
    b7f93bb
  13. RyanCavanaugh commented on Mar 25, 2021

    @RyanCavanaugh
    Member

    There'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.

  14. snarfblam commented on Mar 26, 2021

    @snarfblam

    This is nice. I hope it's a step toward asymmetric accessibility of data properties.

  15. legistek commented on Mar 26, 2021

    @legistek

    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.

  16. codearmadillo commented on Sep 14, 2021

    @codearmadillo

    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 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.

  17. RiftLurker commented on Sep 14, 2021

    @RiftLurker

    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 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.

  18. codearmadillo commented on Sep 14, 2021

    @codearmadillo

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions