Repository navigation
Open
Labels
RevisitAn issue worth coming back toAn issue worth coming back toSuggestionAn idea for TypeScriptAn idea for TypeScript
Description
๐ Search Terms
accessor
decorator
readonly
โ Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
โญ Suggestion
Add readonly as a modifier for accessor fields.
๐ Motivating Example
Suppose you have an injection framework with @provides, @consumes, and @inject. Consider the example
class A {
@provides(Number)
readonly value: number;
@inject([Number])
accessor b = new B();
constructor(value: number) {
this.value = value;
}
}
class B {
@consumes(Number)
readonly value: number;
}Note because @provides is a field decorator, it cannot know when value is assigned unless it's in the initializer. As a consequence, b will not have value injected since @provides doesn't know when to reinject. This is fixed if you do
class A {
@provides(Number)
readonly accessor value: number;
@inject([Number])
accessor b = new B();
constructor(value: number) {
this.value = value;
}
}
class B {
@consumes(Number)
readonly value: number;
}๐ป Use Cases
- What do you want to use this for?
Accessor declarations that shouldn't be modified after being used in the constructor. - What shortcomings exist with current approaches?
You can only mark a field with@readonlyusing JSDoc and just hope that other developers don't touch the field. - What workarounds are you using in the meantime?
@readonlyusing JSDoc
Reacted by Justin Fagnani, mtornwall, snarbies, เซฎเผผโ๏ธฟโเผฝใค, whzx5byb, Alex and Itay Ganor
Metadata
Metadata
Assignees
Labels
RevisitAn issue worth coming back toAn issue worth coming back toSuggestionAn idea for TypeScriptAn idea for TypeScript
Activity
MartinJohns commentedon Aug 7, 2023
This seems intentional: #51820
And in the implementing PR it's explicitly mentioned: #49705
See also this comment: #49705 (comment)
jrandolf commentedon Aug 7, 2023
I see. Ron Buckton (@rbuckton) FWIU from #49705 (comment), the blocker seems to be that accessors also create a setter? I think this is expected. In fact, it's necessary that the accessor creates the setter even in a readonly situation.
The reason is
readonly-members in TypeScript are notreadonlywhen initialized (obviously) or assigned in the constructor. Since accessors do not distinguish assignment in constructor with assignment elsewhere,readonlysetting becomes important. In particular, it's possible to set up event listeners in a constructor that continually modify the member, yet we still want other methods to only access it.jrandolf-old commentedon Mar 22, 2024
Ryan Cavanaugh (@RyanCavanaugh) Ron Buckton (@rbuckton) Any updates here?
rbuckton commentedon Mar 22, 2024
I believe this would directly conflict with the Grouped and Auto Accessors Proposal, and I would rather not have two syntaxes for this.
For the time being, are you able to use a normal getter? If so, this might be an option:
If not, and you are using native decorators, then you could work around this through indirection:
If you are using our legacy
--experimentalDecoratorsoption, then you could work around it in this fashion:I should also note that in the Grouped and Auto-Accessors proposal, this would be accomplished as follows (though the syntax is subject to change at this early stage):
jrandolf-old commentedon Mar 22, 2024
I'm afraid the proposed solutions do not work. We are using native decorators and require the field to be an accessor. Using a normal getter is possible, but for every instance is a lot of boilerplate. I guess I'll put an issue up about this in ts-eslint.
[EDIT: NVM, I just learned that
https://www.npmjs.com/package/eslint-config-standard-with-typescriptwas using an outdated version of ts-eslint...their replacement is also out-dated sadly.]