私人制定者打字稿?

she*_*mus 61 setter accessor getter-setter typescript

有没有办法在TypeScript中为属性设置私有的setter?

class Test
{
    private _prop: string;
    public get prop() : string
    {
        return this._prop;
    }

    private set prop(val: string)
    {
        //can put breakpoints here
        this._prop = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨getter和setter的可见性不匹配.我知道我可以设置支持字段,但是当设置值时我不能设置断点.

我虽然使用接口来隐藏setter,但是接口只能定义一个属性,而不是它是否在setter上有getter.

我在这里错过了什么吗?似乎没有任何理由不允许私有的setter,结果JS不会强制执行可见性,并且似乎比当前的替代品更好.

我错过了什么吗?如果不是,没有私人制定者的充分理由?

Fen*_*ton 56

TypeScript规范(8.4.3)说......

相同成员名称的访问者必须指定相同的可访问性

所以你必须选择一个合适的替代品.这里有两个选项:

你可以没有一个setter,这意味着只有Test该类能够设置属性.您可以在线上放置断点this._prop =....

class Test
{
    private _prop: string;
    public get prop() : string
    {
        return this._prop;
    }

    doSomething() {
        this._prop = 'I can set it!';
    }
}

var test = new Test();

test._prop = 'I cannot!';
Run Code Online (Sandbox Code Playgroud)

可能实现的类似于"通知属性已更改"模式的确保私有访问结果的理想方式是具有一对私有get/set属性访问器和单独的公共get属性访问器.

您仍需要谨慎对待某人后来直接调用支持字段.您可以在该领域发挥创意,尝试降低其可能性.

class Test
{
    private _nameBackingField: string;

    private get _name() : string
    {
        return this._nameBackingField;
    }

    private set _name(val: string)
    {
        this._nameBackingField = val;
        // other actions... notify the property has changed etc
    }

    public get name(): string {
        return this._name;
    }

    doSomething() {
        this._name += 'Additional Stuff';
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案的问题是它们不允许+ =(和 - =)运算符:`this.prop + ='abc';` (2认同)
  • @splintor是的,但不能让其他人更改值是要点:) (2认同)

spl*_*tor 5

我也希望我们可以有公共获取者和私有获取者。在执行此操作之前,另一种处理方法是添加其他私有getter和setter:

class Test {
  _prop: string;
  public get prop(): string {
    return this._prop;
  }

  private get internalProp(): string {
    return this.prop;
  }

  private set internalProp(value: string) {
    this._prop = value;
  }

  private addToProp(valueToAdd: string): void {
    this.internalProp += valueToAdd;
  }
}
Run Code Online (Sandbox Code Playgroud)


ctw*_*els 5

概述

这里提供的答案有点过时,尽管对于 TypeScript 4.2 及更低版本来说非常有用。根据 TypeScript 的更新文档从 TypeScript 4.3 开始可以实现这一点

从 TypeScript 4.3 开始,可以使用不同类型的访问器来进行获取和设置。

这是实际拉取请求的链接以及下面显示此新功能的代码片段。


代码

下面,something访问器具有不同的可见性(public getprivate set)。

请参阅 TypeScript Playground 中的工作原理

class A {
  #somethingPrivate: number = 0;

  public get something(): number {
    return this.#somethingPrivate;
  }

  private set something(newValue: number) {
    this.#somethingPrivate = Math.max(0, newValue);
  }

  public decrease(): A {
    this.something--;
    return this;
  }

  public increase(): A {
    this.something++;
    return this;
  }
}

const a = new A();
a.increase();
console.log(a.something); // 1

a.decrease().decrease().decrease();
console.log(a.something); // 0
Run Code Online (Sandbox Code Playgroud)

注意:如果您想知道它的#member作用,它使它在运行时真正私有。请参阅此处的文档以及有关此问题的精彩答案。