9

We have a typical getter in one of our classes, lets say

class Employee implements IEmployee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }
}

and an interface to work with it

interface IEmployee{
     fullName: string; 
}

When working with an instance via this interface the compiler will not warn us about absence of a setter if we try to assign to fullName, and the the JS runtime simply swallows any assignment and does not throw an error. Is there any way to mark interface member as having only getter or only setter?

I've seen this post, but it is quite old, i want to know, if anything improved.

Community
  • 1
  • 1
Ivan Koshelev
  • 3,830
  • 2
  • 30
  • 50
  • Really surprised at the lack of activity for this question. Read only properties are incredibly useful and one of the first patterns I tried to implement in TypeScript. – gravidThoughts Apr 16 '15 at 18:19

2 Answers2

2

Properties in typescript can now have 'readonly' modifier, which achieves the desired restult.

interface IEmployee{
    readonly fullName: string; 
}
Ivan Koshelev
  • 3,830
  • 2
  • 30
  • 50
1

This is an interesting question. The concept of a readonly property is subtly different in TypeScript to other languages.

In many languages a property with a getter (but no setter) would raise a compiler error if you attempted to set the property, but TypeScript doesn't.

The property is still readonly, because it makes no difference if you attempt to set it; the set will fail silently.

Here is an example without any interfaces:

class Example {
    get name() {
        return 'Steve';
    }
}

var y = new Example();
y.name = 'Example 2';
alert(y.name);

There is no compiler warning when I use x.name = 'Example 2';.

If there was a compiler warning, I would subsequently expect there to be a way of specifying the readonly-ness of a property within an interface. As you'd expect though, given the above information, you can't set a readonly property on an interface.

interface Test {
    name: string;
}

class Example {
    get name() {
        return 'Steve';
    }
}

var x: Test = new Example();
x.name = 'Example 1';
alert(x.name);

var y = new Example();
x.name = 'Example 2';
alert(x.name);

This means you can only enforce readonly-ness by having a method to get the value of the property (and obviously no method that allows it to be set).

interface Test {
    getName: () => string;
}

class Example {
    getName() {
        return 'Steve';
    }
}

var x: Test = new Example();
//x.getName('Obviously not');
//x.getName() = 'Obviously not';
alert(x.getName());

var y = new Example();
//y.getName('Obviously not');
//y.getName() = 'Obviously not';
alert(y.getName());
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • Readonlyness is pretty much enforced already by JS behavior in absence of a setter. The problem is its silent nature - quietly swallowing the value. Ideal (and hopefully coming) solution would be allowing TS interface members to be marked as having only getter \ setter. Alternative would be for the transpiler to generate empty getter setter in absence of thereof, which would simply throw an error (at least for a setter this is the behavior our entire team expected). The final tedious solution would be to always make a throwing setter by hand if no actual setter is needed. – Ivan Koshelev Oct 03 '14 at 15:30
  • `Readonlyness is pretty much enforced already by JS behavior in absence of a setter.` yes - although by "enforced", I was talking more about a compiler warning, squiggly red lines and some kind of audible alarm. The example code shows the silent discard of the set attempt. In the meantime, using a method for property access is the only way to get compile time guarantees that no set attempt is being attempted. – Fenton Oct 03 '14 at 15:48
  • Made an issue on GitHub about this problem https://github.com/Microsoft/TypeScript/issues/814 – Ivan Koshelev Oct 03 '14 at 20:42