2

Given the following code:

class foo {
    protected mBar: string;
    public get Bar(): string {
        return this.mBar;
    }
}

function foobar(): void {
    var myFoo: foo = new foo();

    myFoo.Bar = "hello";
}
foobar();

Why doesn't the line myFoo.Bar = "hello"; generate a compiler error? I would expect a compiler error since foo only defines a get Bar() but NOT a set Bar(). Instead, the compiler says nothing, and the resulting javascript runs, but fails silently. There's no indication by either the compiler or at runtime that the setter did not work as expected. Shouldn't this situation be flagged by the typescript compiler?

EDIT: Just to provide some context, this occurred by accident. I forgot to define the setter, and then proceeded to waste a bit of time trying to figure out why my assignment wasn't working as expected. If the compiler had simply complained saying I was trying to assign to a property when no setter was defined it would have saved some wasted effort.

RJM
  • 1,164
  • 9
  • 21

2 Answers2

1

Not creating a setter does not mean you cannot set it. It means it will be set without a setter. TypeScript works like JavaScript when you don't give it modifiers.

Also you cannot make a getter be public and the setter private. See Private setter typescript? Thanks to thedayturns for that information in the comments.

There's an issue tracking this problem at https://github.com/Microsoft/TypeScript/issues/12

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • 3
    You can't have a private setter with a public getter. http://stackoverflow.com/questions/27825350/private-setter-typescript – thedayturns Feb 19 '16 at 21:12
  • Is there a modifier that will make it work the way I was expecting? – RJM Feb 19 '16 at 21:35
  • @RJM I'm not aware of a way to create private setters with public getters. See the question linked here by thedayturns – Ruan Mendes Feb 19 '16 at 21:46
-1

Just because its defined as a getter doesn't mean you can't set the returned value. When you return the value, you change it to "hello" after it's been returned, which is legal.

What you are not doing with this statement is changing the actual value within the object. You'll notice if you call the getter again after this statement, it'll return the value you define it as in the setter or upon object instantiation.

You should read some more on the purpose of getter and setter methods to understand what they are and why (and when!) they are used, as it is an absolutely vital concept for Object Oriented Programming

Jodo1992
  • 745
  • 2
  • 10
  • 32
  • Thanks. Yes, I understand that the code above is not correct. My question is not what is wrong with the code...my question is why did the compiler not complain that this code is not correct. – RJM Feb 20 '16 at 15:00
  • 1
    Because from the compilers standpoint there is nothing incorrect about the code. You are allowed to use a getter to get a value and then overwrite that instance, it just won't change the instance inside the object – Jodo1992 Feb 20 '16 at 17:18
  • Hmmm. But the code I provided above isn't using the getter at all, it's using Bar as a setter. And the setter was not declared, hence my question. – RJM Feb 20 '16 at 17:29
  • 'myFoo.Bar' is a way of using the getter you defined. You are indeed using the getter in this statement since it is a public method – Jodo1992 Feb 20 '16 at 17:32
  • I don't think that's correct. myFoo.Bar is a way of using the getter when it is used as an element in an expression, But when used as the target of an assignment it does NOT use the getter, it uses a setter in that case. And my concern is that since I did not define the setter, the compiler should have complained that I was using Bar in a context where a setter is needed, but none was defined. – RJM Feb 20 '16 at 17:42
  • Hmm I will have to run this in an environment and debug to analyze further. I now see your point – Jodo1992 Feb 20 '16 at 17:56
  • I put the code above into the typescript playground at the link below, and added an alert to the getter method. It shows that the getter is not getting called: [link](http://www.typescriptlang.org/Playground#src=class%20foo%20{%0A%09protected%20mBar%3A%20string%3B%0A%09public%20get%20Bar%28%29%3A%20string%20{%0A%09%09alert%28%22Bar%20getting%20called.%22%29%3B%0A%09%09return%20this.mBar%3B%0A%09}%0A}%0A%0Afunction%20foobar%28%29%3A%20void%20{%0A%09var%20myFoo%3A%20foo%20%3D%20new%20foo%28%29%3B%0A%09myFoo.Bar%20%3D%20%22hello%22%3B%0A}%0Afoobar%28%29%3B%0A) – RJM Feb 20 '16 at 18:14
  • Why exactly are you defining mBar as protected? I have a hunch it has something to do with this. – Jodo1992 Feb 20 '16 at 18:32
  • Protected mBar is correct. It makes sense with the correct code. Here is the correct code: [link](http://www.typescriptlang.org/Playground#src=class%20foo%20{%0A%09protected%20mBar%3A%20string%3B%0A%09public%20get%20Bar%28%29%3A%20string%20{%0A%09%09alert%28%22Bar%20getting%20called.%22%29%3B%0A%09%09return%20this.mBar%3B%0A%09}%0A%09public%20set%20Bar%28value%3A%20string%29{%0A%09%09this.mBar%20%3D%20value%3B%0A%09}%0A}%0A%0Afunction%20foobar%28%29%3A%20void%20{%0A%09var%20myFoo%3A%20foo%20%3D%20new%20foo%28%29%3B%0A%09myFoo.Bar%20%3D%20%22hello%22%3B%0A}%0Afoobar%28%29%3B%0A) – RJM Feb 20 '16 at 18:48