TypeScript 允许只读访问器 ```markdown 允许只读访问器 ```

h9a6wy2h  于 8个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(122)

🔍 搜索词

访问器
装饰器
只读

✅ 可实现性检查清单

  • 这不会对现有的TypeScript/JavaScript代码造成破坏性的改变
  • 这不会改变现有JavaScript代码的运行时行为
  • 这可以在不根据表达式的类型发出不同的JS的情况下实现
  • 这不是一个运行时特性(例如库功能,带有JavaScript输出的非ECMAScript语法,JS的新语法糖等)
  • 这个特性将符合我们设计目标的其他部分: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ 建议

accessor 字段添加 readonly 作为修饰符。

📃 激励示例

假设你有一个带有 @provides@consumes@inject 的注入框架。考虑以下示例:

  1. class A {
  2. @provides(Number)
  3. readonly value: number;
  4. @inject([Number])
  5. accessor b = new B();
  6. constructor(value: number) {
  7. this.value = value;
  8. }
  9. }
  10. class B {
  11. @consumes(Number)
  12. readonly value: number;
  13. }

注意,由于 @provides 是字段装饰器,它无法在初始化时知道何时分配 value 。因此, b 将不会注入 value ,因为 @provides 不知道何时重新注入。如果这样做:

  1. class A {
  2. @provides(Number)
  3. readonly accessor value: number;
  4. @inject([Number])
  5. accessor b = new B();
  6. constructor(value: number) {
  7. this.value = value;
  8. }
  9. }
  10. class B {
  11. @consumes(Number)
  12. readonly value: number;
  13. }

问题就会得到解决。

💻 用例

  1. 你打算用这个做什么?
    需要在构造函数中使用后不应再修改的访问器声明。
  2. 目前方法的缺点是什么?
    你只能使用JSDoc标记一个字段为 @readonly ,然后希望其他开发者不要触碰该字段。
  3. 在等待期间,你正在使用什么解决方法?
    使用JSDoc标记 @readonly
bf1o4zei

bf1o4zei1#

这似乎是有意为之: #51820
在实施PR中,它明确提到: #49705
accessor 不能与 readonlydeclare 在同一个字段声明上一起使用。
另请参阅此注解: #49705 (评论)

shyt4zoc

shyt4zoc2#

我明白了。@rbuckton FWIU来自#49705(评论),阻止器似乎是访问器也创建了一个setter?我认为这是意料之中的。事实上,即使在只读情况下,访问器也需要创建setter。
原因是TypeScript中的成员在初始化时(显然)或在构造函数中分配时不是readonly。由于访问器不区分构造函数中的赋值与其他地方的赋值,因此readonly设置变得重要。特别是,可以在构造函数中设置事件监听器,以不断修改成员,但我们仍然希望其他方法只能访问它。

e4eetjau

e4eetjau3#

@RyanCavanaugh @rbuckton 有任何更新吗?

cvxl0en2

cvxl0en24#

我相信这将直接与Grouped and Auto Accessors Proposal冲突,我宁愿不要有两种语法。
目前,你能使用普通的getter吗?如果可以,这可能是一个选项:

  1. class A {
  2. #value: number;
  3. @provides(Number)
  4. get value() { return this.#value; }
  5. @inject([Number])
  6. accessor b = new B();
  7. constructor(value: number) {
  8. this.value = value;
  9. }
  10. }

如果不行,而且你正在使用原生装饰器,那么你可以通过间接方式解决这个问题:

  1. class A {
  2. @provides(Number)
  3. #value: number;
  4. get value() { return this.#value; }
  5. @inject([Number])
  6. accessor b = new B();
  7. constructor(value: number) {
  8. this.#value = value;
  9. }
  10. }

如果你正在使用我们的传统--experimentalDecorators选项,那么你可以以这种方式解决它:

  1. class A {
  2. @provides(Number)
  3. private _value: number;
  4. get value() { return this._value; }
  5. @inject([Number])
  6. accessor b = new B();
  7. constructor(value: number) {
  8. this._value = value;
  9. }
  10. }

我还应该指出,在Grouped和Auto-Accessors提案中,这是通过以下方式完成的(尽管在这个早期阶段,语法可能会发生变化):

  1. class A {
  2. @provides(Number)
  3. accessor value: number { get; #set; }
  4. @inject([Number])
  5. accessor b = new B();
  6. constructor(value: number) {
  7. this.#value = value;
  8. }
  9. }
展开查看全部
8wtpewkr

8wtpewkr5#

恐怕提出的解决方案不起作用。我们正在使用原生装饰器,并要求字段是一个访问器。使用普通的getter是可能的,但对于每个示例都有很多样板代码。我想我会在ts-eslint上提出一个关于这个问题的问题。
[编辑:NVM,我刚刚了解到https://www.npmjs.com/package/eslint-config-standard-with-typescript正在使用ts-eslint的过时版本...他们的替代品也很遗憾地过时了。]

相关问题