Reputation: 3
I have a class which contains a private property which is an array. There is a public getter and setter to ensure that data manipulation triggers required business logic.
I ran into a problem, when a caller was able to set the private property without running the associated logic contained in the public setter.
I reproduced the issue with this simple code:
class Greeter {
private _greetings: string[];
constructor () {}
set greetings(greetings: string[]) {
let newGreetings: string[] = [];
for (let i: number = 0; i < greetings.length; i++) {
newGreetings.push("setter_" + greetings[i] )
}
this._greetings = newGreetings;
}
get greetings() {
return this._greetings;
}
}
let greeter = new Greeter();
greeter.greetings = ["test"];
let test1 = document.createElement('p');
test1.textContent = greeter.greetings[0];
document.body.appendChild(test1);
greeter.greetings[0] = "test";
let test2 = document.createElement('p');
test2.textContent = greeter.greetings[0];
document.body.appendChild(test2);
To view the code in TS playground, follow the below link:
My question is: Am I doing something wrong? Is this the intended behavior? Or is this more of an issue with typescript compiler which should not allow this code to compile?
Upvotes: 0
Views: 29
Reputation: 220884
Looking specifically at these two lines:
greeter.greetings = ["test"];
and
greeter.greetings[0] = "test"
They look similar, but they're really quite different. This line here says set the greetings
property of greeter
to ["test"]
. The greetings
setter is invoked because we're setting the greetings
property.
greeter.greetings = ["test"];
In contrast, this line should really be thought of as two operations
// this line...
greeter.greetings[0] = "test"
// ...is the same as
const tmp = greeter.greetings;
tmp[0] = "test";
As you can see, we don't set the greetings
property, we get it! Then we set a property of the array. The greetings
setter is not used.
Starting in TypeScript 2.0 (in beta at time of writing) you'll be able to use ReadonlyArray<string>
to represent arrays that can be read but not written to. This will let you expose a ReadonlyArray<string>
to consumers but have a regular string[]
as a private
field.
Upvotes: 1