TypeScript: Why am I able to modify `readonly` property in constructor?

From the TypeScript documentation:

Read-only properties may have initializers and may be assigned to in constructors within the same class declaration, but otherwise assignments to read-only properties are disallowed.

More about the readonly keyword


The docs only say

Readonly properties must be initialized at their declaration or in the constructor. (Source)

But as Romain pointed out there is a little more info in the TypeScript 2.0 release notes:

Read-only properties may have initializers and may be assigned to in constructors within the same class declaration, but otherwise assignments to read-only properties are disallowed. (Source)


But what confuses me is the compiled output. See an example on the TS Playground.

As you can see the initially (readonly) property is overwritten without any warning from TS at compile time. I guess this is intentional, because the language behaves the same all the time and there are less edge cases.

EDIT: There is also a "sugarized" way to initialize a class with properties in TypeScript (I guess you know that but anyway):

Adding public/private to arguments of the constructor signature will initialize those arguments as class properties. So in your example:

class Jedi { 
    constructor(
        private readonly name: string = 'Skywalker'
    ) {}

    toString():string {
        return this.name;
    }
}

And if let TypeScript compile the above code, it actually works as expected (or at least what I would expect). There is another Link to the Playground.

tl;dr; Initializing class properties inside the constructor signature via public/private will set the default value if none is given. This does not work if you set class properties "by hand" (this.name = name). The later might still not be a bug but rather an intentional behaviour, because you explicitly set the class property.

You can avoid this issue (or at least have TypeScript scream at you) by enabling noImplicitAny and strictNullChecks. This way TypeScript will let you know that your class property might be undefined.


What I would suggest is not using readonlyproperty if you want to have immutability. Not only is the above mentioned kinda weird behaviour, some less experienced developers might also think that a readonly array/object is really fully frozen/read only where it isn't. Rather use something like ImmutableJS.

Tags:

Typescript