свойства только для чтения и ngOnInit - PullRequest
0 голосов
/ 01 марта 2019

Свойства только для чтения могут быть назначены только в конструкторе, но в angular это не рекомендуется и иногда невозможно использовать конструктор для определенной инициализации, и вместо этого используется угловой хук ngOnInit.Есть ли способ пометить ngOnInit как конструктор в отношении атрибута readonly, чтобы я мог использовать readonly для по существу неизменяемых свойств, которые назначаются только один раз в ngOnInit?

edit: уточнить: im not lookдля альтернативных способов объявить свойства только для чтения.Я хочу объявить их обычным способом.Что-нибудь еще, я думаю, не стоило бы идти на компромисс в удобочитаемости, просто чтобы получить эту статическую проверку.Я надеялся, что будет какая-то аннотация, как для tslint, чтобы игнорировать неизменность внутри ngOnInit.

Из ответов на этот вопрос я предполагаю, что назначение их как (this as any).foo = bar; является наиболее близким к тому, что я хотел бы сделать,хотя я полагаю, что это все-таки уродливее, чем просто опустить чтение.

Ответы [ 4 ]

0 голосов
/ 01 марта 2019

Свойства только для чтения могут быть назначены только в конструкторе

Не верно

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

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

Как видите, уже есть 3 способа их определения.И, вероятно, больше!

, но в angular это не рекомендуется и иногда невозможно использовать конструктор для определенной инициализации, а вместо этого используется угловой хук ngOnInit

It "не рекомендуется«для новичков, потому что им проще сказать не делать этого, чем подробно объяснять жизненный цикл фреймворка.Дело в том, что вы можете использовать конструктор по своему усмотрению, особенно для вещей, не связанных с Angular (например, переменные только для чтения).

Есть ли способ пометить ngOnInit как конструктор

Конструктор - это конструктор.Вы не можете определить метод, который будет конструктором.Вы можете вызвать только метод в конструкторе, но это не решит вашу проблему.

, чтобы я мог использовать только для чтения по существу неизменяемые свойства, которые назначаются только один раз в ngOnInit?

Ответ и нижняя строка: использовать ваш конструктор какпожалуйста Поместите свои свойства только для чтения, если хотите.

Кроме того, рассмотрите возможность предоставления некоторой песочницы или хотя бы некоторого кода, чтобы мы могли дать ответ, адаптированный как к вашему коду, так и к вашим потребностям.

0 голосов
/ 01 марта 2019

Почему бы вам не использовать сеттер и геттер вместо 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;
  }
}
0 голосов
/ 01 марта 2019

Это хороший вопрос. Вы можете получить нечто подобное через сеттер:

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

0 голосов
/ 01 марта 2019

Вы не можете пометить метод как конструктор, для этого просто нет синтаксиса.Вы можете нарушить 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 = ""
    }
}
...