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

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

🔍 搜索词

访问器
装饰器
只读

✅ 可实现性检查清单

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

⭐ 建议

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

📃 激励示例

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

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;
}

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

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;
}

问题就会得到解决。

💻 用例

  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吗?如果可以,这可能是一个选项:

class A {
  #value: number;

  @provides(Number)
  get value() { return this.#value; }

  @inject([Number])
  accessor b = new B();

  constructor(value: number) {
    this.value = value;
  }
}

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

class A {
  @provides(Number)
  #value: number;
  
  get value() { return this.#value; }

  @inject([Number])
  accessor b = new B();

  constructor(value: number) {
    this.#value = value;
  }
}

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

class A {
  @provides(Number)
  private _value: number;
  
  get value() { return this._value; }
  
  @inject([Number])
  accessor b = new B();

  constructor(value: number) {
    this._value = value;
  }
}

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

class A {
  @provides(Number)
  accessor value: number { get; #set; }

  @inject([Number])
  accessor b = new B();

  constructor(value: number) {
    this.#value = value;
  }
}
8wtpewkr

8wtpewkr5#

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

相关问题