1

在 TypeScript 中,在一个类中,是否有一种优雅的方法可以只设置一次值?换句话说,是否有相当于readonly在给它一个值之后设置一个值?

例如:

class FooExample {
    public fixedValue: string;

    public setFixedValue(value: string): void {
        if (!this.fixedValue) {
            // this value should be immutable
            this.fixedValue = value;
        }
    }
}

我不是在寻找吸气剂,因为类属性可以在类本身内更改。

4

2 回答 2

0

您可以使用“智能”设置器来实现此目的。想法是在类上定义一个 setter,从其自身中删除 setter,并通过使用属性设置为Object.defineProperty的描述符调用的方法定义一个只读属性。writablefalse

“类本身的变化”部分可以通过另一个属性重新定义来实现。不要忘记首先制作财产configurable

这是完整的样子(我认为没有更优雅的方法可以做到这一点) - 答案的运行时版本不是 TypeScript 特定的:

class ReadonlyFields {
  set fixed(value) {
    Object.defineProperty(this, "fixed", {
      value,
      writable: false,
      configurable: true,
    });
  }

  doSomething() {
    Object.defineProperty(this, "fixed", {
      value: 24, //exact logic for changing the value is up to you
      writable: false
    });
  }
}

const r = new ReadonlyFields();
r.fixed = 42;
console.log(r.fixed); //42;
r.fixed = 24;
console.log(r.fixed); //42;
r.doSomething();
console.log(r.fixed); //24;

如果您还想从类型系统的角度强制执行此操作,只需创建属性readonly

class ReadonlyFields {
  readonly fixed!: number;

  setFixed(value: number) {
    Object.defineProperty(this, "fixed", {
      value,
      writable: false,
      configurable: true,
    });
  }

  doSomething() {
    Object.defineProperty(this, "fixed", {
      value: 24, //exact logic for changing the value is up to you
      writable: false,
    });
  }
}

const r = new ReadonlyFields();
r.setFixed(42); //OK
//@ts-expect-error
r.fixed = 24;
r.doSomething(); //OK
于 2021-05-26T07:48:42.527 回答
0

在阅读了建议的答案并进行了自己的研究之后,我相信我已经找到了最优雅的解决方案。您首先将值定义为 an Object,然后freeze()Object填充相关属性之后定义。

class FooExample {
    public fixedValue = {
        value: '';
    };

    public setFixedValue(value: string): void {
        if (!Object.isFrozen(this.fixedValue)) {
            this.fixedValue.value = value;
            Object.freeze(this.fixedValue);
        }
    }
}
于 2021-06-04T04:00:54.153 回答