简体   繁体   English

readonly属性和ngOnInit

[英]readonly properties and ngOnInit

Readonly properties can only be assigned in the constructor, but in angular it is discouraged and sometimes impossible to use the constructor for certain initialization and instead the angular hook ngOnInit is used. 只能在构造函数中指定只读属性,但是不鼓励使用构造函数进行某些初始化,而不是使用角度挂钩ngOnInit。 Is there any way to mark ngOnInit as a constructor with regard to the readonly attribute so that I can use readonly for essentially immutable properties that are only assigned a single time in ngOnInit? 有没有办法将ngOnInit标记为关于readonly属性的构造函数,以便我可以将readonly用于基本上不可变的属性,这些属性只在ngOnInit中分配一次?

edit: To clarify: im not looking for alternative ways to declare readonly properties. 编辑:澄清:我不寻找声明只读属性的替代方法。 I want to declare them the regular way. 我想以常规方式宣布它们。 Anything else I think would not be worth the tradeoff in readability just to get that static check. 我认为任何其他的东西都不值得在可读性方面进行权衡以获得静态检查。 I was hoping there would be some annotation like there are for tslint to ignore the immutability inside ngOnInit. 我希望会有一些注释,就像tslint忽略ngOnInit中的不变性一样。

From the answers so far I guess assigning them as (this as any).foo = bar; 从答案到目前为止,我猜测将它们分配为(this as any).foo = bar; is the closest to what I would like to do, though I guess it's still uglier than just leaving out the readonly. 是最接近我想做的事情,虽然我想它仍然比仅仅遗漏读者更丑陋。

Readonly properties can only be assigned in the constructor 只能在构造函数中分配只读属性

Not true 不对

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

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

As you see, there is already 3 ways of defining them. 如您所见,已有3种方法可以定义它们。 And probably more ! 可能还有更多!

but in angular it is discouraged and sometimes impossible to use the constructor for certain initialization and instead the angular hook ngOnInit is used 但是在角度上它是不鼓励的,有时不可能使用构造函数进行某些初始化,而是使用角度钩子ngOnInit

It is "discouraged" for newcomers, because it's easier to tell them not to do that, rather than explaining in depth the lifecycle of the framework. 它对新手来说是“沮丧的”,因为告诉他们不要这样做更容易,而不是深入解释框架的生命周期。 The point is, you can use the constructor as you please, especially for stuff unrelated to Angular (like read-only variables). 关键是,您可以根据需要使用构造函数,尤其是与Angular无关的内容(如只读变量)。

Is there any way to mark ngOnInit as a constructor 有没有办法将ngOnInit标记为构造函数

A constrcutor is a constructor. 建筑师是建筑师。 You can't define a method to be a constructor. 您不能将方法定义为构造函数。 You can only call a method in the constructor, but that won't solve your issue. 您只能在构造函数中调用方法,但这不会解决您的问题。

so that I can use readonly for essentially immutable properties that are only assigned a single time in ngOnInit? 所以,我可以使用readonly基本上不可变的属性,只在ngOnInit中分配一次?

Answer and bottom line : use your constructor as you please . 答案和底线:根据需要使用您的构造函数 Put your readonly properties in it if you want. 如果需要,可以将您的只读属性放入其中。

Also, consider providing some sandbox or at least some code, so that we can make an answer that is adapted to both your code and your need. 另外,考虑提供一些沙箱或至少一些代码,以便我们可以做出适合您的代码和需求的答案。

You can't mark a method as a constructor there is just no syntax for that. 您不能将方法标记为构造函数,只是没有语法。 You can break the readonly which is just a compile time check by using a type assertion to any and access any public/private property you want in a type unsafe way. 您可以通过对any类型断言使用类型断言来中断readonly ,这只是一个编译时检查,并以类型不安全的方式访问您想要的任何公共/私有属性。 You can also use a mapped type to make the type mutable, but it only works for public properties: 您还可以使用映射类型使类型可变,但它仅适用于公共属性:

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 = ""
    }
}

Why don't you use a setter and a getter in place of readonly ? 你为什么不用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;
  }
}

That is a good question. 这是一个很好的问题。 You could get something similar going on via a setter: 你可以通过setter获得类似的东西:

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

Yet another way to get similar behavior would be to encapsulate the read only member in a class, put it in your component and create a new instance of the class in ngInit or some other component initialization function. 获得类似行为的另一种方法是将只读成员封装在类中,将其放入组件中并在ngInit或其他组件初始化函数中创建类的新实例。

Considering Object.defineProperty exists, a better way would be to use it as pointed out by @trichetriche 考虑到Object.defineProperty存在,更好的方法是使用@trichetriche指出的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 初始化ngOnInit范围内的属性 - Initializing properties inside ngOnInit scope 如何观察 JavaScript 中 HTMLElement 的只读属性? - How to observe readonly properties of an HTMLElement in JavaScript? 如何调整 Temporal ZonedDateTime 的只读属性? - How to adjust the readonly properties for Temporal ZonedDateTime? 初始化指令的数据绑定属性之后调用的生命周期挂钩(ngOnInit) - Lifecycle hook that is called after data-bound properties of a directive are initialized (ngOnInit) ReactJs/Typescript:使组件 state object 和属性只读 - ReactJs/Typescript: Make component state object and properties readonly breezejs:非标量导航属性为只读(多对多问题) - breezejs: Nonscalar navigation properties are readonly (Many-to-many issue) 如何在JSDoc中注释“@ readonly-but-modified-internal”成员/属性? - How to annotate “@readonly-but-modified-internally” members / properties in JSDoc? TypeScript属性中readonly与get之间有什么区别? - What are the differences between readonly vs get in TypeScript properties? ngOnInit 组件错误,这不是 component.ngOnInit 中的函数 - ngOnInit component error , this is not a function at component.ngOnInit TypeError:当我添加一个接口来解决只读属性错误时,无法读取 null 的属性 - TypeError: Cannot read properties of null when I add an interface to resolve Readonly property error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM