TypeScript中特定getter/setter的工作原理及底层值疑问
Great question! Let's break this down step by step to clear up the confusion around how these getters/setters work, what their underlying values are, and why you don't see that var _prop declaration in the compiled ES2015 code.
First: The Critical Issue with this.prop in Both Getter and Setter
If you’ve written code where both the getter and setter reference this.prop directly (like the example below), you’re running into a fatal problem: infinite recursion.
class BadExample { get prop() { return this.prop; // ❌ Triggers the getter again... infinitely } set prop(value) { this.prop = value; // ❌ Triggers the setter again... infinitely } }
Every time you try to read instance.prop, the getter fires, which tries to read this.prop again—looping forever. Same goes for assignment: setting instance.prop = "foo" triggers the setter, which tries to assign to this.prop, firing the setter once more. This will crash your code with a stack overflow error.
The Correct Approach: Underlying Storage Variables
To make getters/setters work properly, you need a separate underlying storage variable to hold the actual value. This is almost always a private variable (conventionally prefixed with an underscore like _prop, or using TypeScript’s true private fields with #).
Here’s the fixed version:
class GoodExample { // Private storage variable (compiled to a regular instance property in ES2015) private _prop: string; get prop() { return this._prop; // ✅ Reads the actual stored value } set prop(value: string) { this._prop = value.trim(); // ✅ Writes to storage (with optional logic!) } }
In this case, this._prop is the real value holder. The getter just returns it, and the setter can add logic (like trimming whitespace) before updating it.
Why No var _prop in the Compiled ES2015 Code?
When TypeScript compiles this to ES2015, you’ll end up with code like this:
class GoodExample { get prop() { return this._prop; } set prop(value) { this._prop = value.trim(); } }
You won’t see a var _prop declaration here because _prop is an instance property, not a local variable. Here’s why:
- Instance properties are attached to the class instance (via
this) when they’re first assigned. When you runthis._prop = value, JavaScript automatically creates the property on the instance if it doesn’t exist yet. - Local variables (declared with
var,let, orconst) are scoped to a function or block, but_propneeds to persist across multiple calls to the getter/setter—so it has to live on the instance itself.
If you initialized _prop in the constructor (e.g., this._prop = "default"), you’ll see that assignment in the compiled constructor, but still no var declaration—because again, it’s an instance property, not a local variable.
Bonus: True Private Fields (ES2022+)
If you use TypeScript’s true private fields (with #), like this:
class TruePrivateExample { #prop: string; // Native private field get prop() { return this.#prop; } set prop(value: string) { this.#prop = value; } }
The compiled ES2022 code will use JavaScript’s native private field syntax (#prop), which is enforced by the engine—no way to access it from outside the class. You still won’t see a var declaration here, since it’s a class-level private field.
To Sum Up
- Never use
this.propdirectly in both getter and setter—it causes infinite recursion. Always use an underlying storage variable. - The
_prop(or#prop) in compiled code is an instance property, not a local variable, so you won’t see avardeclaration for it. It’s created automatically when you first assign tothis._prop.
内容的提问来源于stack exchange,提问作者keldar

