只读属性和ngOnInit

时间:2019-03-01 09:47:28

标签: javascript angular typescript readonly-attribute

只读属性只能在构造函数中分配,但是不鼓励在angular中使用,有时无法使用构造函数进行某些初始化,而是使用Angular钩子ngOnInit。 是否有任何方法可以将ngOnInit标记为关于readonly属性的构造函数,以便我可以对本质上不可变的属性(仅在ngOnInit中分配一次)使用readonly?

编辑:澄清:我不寻找声明只读属性的替代方法。我想以常规方式声明它们。我认为仅仅为了进行静态检查就不值得在可读性上进行权衡。 我希望会有一些注释,例如tslint可以忽略ngOnInit内部的不变性。

到目前为止,我想将答案分配为(this as any).foo = bar;是我想做的最接近的答案,尽管我认为它比仅保留只读项还要难看。

4 个答案:

答案 0 :(得分:3)

  

只读属性只能在构造函数中分配

不正确

class MyClass {
  readonly prop1 = 'prop1';
  constructor(
    public readonly prop2 = 'prop2'
  ) {
  }

  ngOnInit() {
    Object.defineProperty(this, 'prop3', { wirtable: false, value: 'prop3'});
  }
}

如您所见,已经有3种定义它们的方法。可能还有更多!

  

但是不鼓励使用角度函数,有时甚至无法使用构造函数进行某些初始化,而是使用角度钩子ngOnInit

对于新来者来说,这是“令人沮丧的”,因为告诉他们不要这样做,比深入解释框架的生命周期更容易。关键是,您可以随意使用构造函数,尤其是对于与Angular不相关的东西(例如只读变量)。

  

是否可以将ngOnInit标记为构造函数

构造函数是构造函数。您不能将方法定义为构造函数。您只能在构造函数中调用方法,但这无法解决您的问题。

  

以便我可以对本质上不可变的属性(仅在ngOnInit中分配一次)使用只读?

答案和底线:随心所欲地使用构造函数。如果需要,将您的只读属性放入其中。

此外,请考虑提供一些沙箱或至少提供一些代码,以便我们做出适合您的代码和需求的答案。

答案 1 :(得分:2)

您不能将方法标记为构造函数,只是没有语法。您可以通过对readonly使用类型断言来破坏any,这只是编译时检查,并以类型不安全的方式访问所需的任何公共/私有属性。您还可以使用映射类型使该类型可变,但它仅适用于公共属性:

type Mutable<T> = { -readonly [ P in keyof T]: T[P] }

class Foo {
    public readonly data: string;
    private readonly pdata: string;
    public init() {
        const ref: Mutable<this> = this;
        ref.data = "" 
        const pRef = this as any;
        pRef.pdata = ""

        const pSaferRef: { pdata: string } = this as any;
        pSaferRef.pdata = ""
    }
}

答案 2 :(得分:2)

为什么不使用setter和getter来代替readonly

export class MyComponent {
  private _value: string;
  set value(v: string) {
    if (!this._value) {
      this._value = v;
    } else {
      throw new TypeError('Assignment to read-only variable');
    }
  }

  get value() {
    return this._value;
  }
}

答案 3 :(得分:0)

这是一个好问题。 通过二传手可以得到类似的结果:

...
    protected _pseudoReadonlyProp: number = -1 // or some other value, that marks unititialized state
    set pseudoReadonlyProp(a: number) {
        if(this._pseudoReadonlyProp != -1) {
           // throw some error here
        }
        this._pseudoReadonlyProp = a
    }
    get pseudoReadonlyProp(): number {
        return this._pseudoReadonlyProp
    }
...

获得类似行为的另一种方法是将只读成员封装在一个类中,将其放入组件中,然后在ngInit或某些其他组件初始化函数中创建该类的新实例。 。

考虑到Object.defineProperty的存在,一种更好的方法是使用@trichetriche指出的