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