ウェブサイト検索

javascript - 読み取り専用プロパティと ngOnInit


読み取り専用プロパティはコンストラクタ内でのみ割り当てることができますが、Angularではコンストラクタを使用することは推奨されておらず、特定の初期化ではコンストラクタを使用できないこともあります。その代わりに、AngularのフックであるngOnInitが使用されます。ngOnInitを読み取り専用属性に関してコンストラクタとしてマークし、ngOnInit内で一度だけ割り当てる本質的に不変のプロパティにreadonlyを使用する方法はありますか?

編集: 明確にするために言うと、私はreadonlyプロパティを宣言する別の方法を探しているわけではありません。通常の方法で宣言したいのです。それ以外の方法は、静的チェックを得るためだけに可読性を犠牲にする価値はないと思います。tslintのようにngOnInit内の不変性を無視する注釈があるのではないかと思っていました。

これまでの回答からすると、(this as any).foo=bar; と割り当てるのが私のやりたいことに最も近いと思いますが、readonly を省くよりはまだ見た目が悪い気がします。

回答 #1

読み取り専用プロパティは、コンストラクター内でのみ割り当てることができます

本当ではない

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

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

ご覧の通り、すでにそれらを定義する方法は3つあります。そしておそらくもっとあるでしょう!

しかし、Angularではコンストラクタを使用して特定の初期化を行うことは推奨されておらず、場合によっては不可能であり、代わりにAngularのフックであるngOnInitが使用されます

初心者には「控えるように」と言われることがあります。なぜなら、フレームワークのライフサイクルを詳しく説明するよりも、それをしないように伝える方が簡単だからです。重要なのは、コンストラクタは自由に使えるということです。特に Angular に関係のない内容(読み取り専用の変数など)についてはそうです。

ngOnInit をコンストラクタとしてマークする方法はありますか

コンストラクタはコンストラクタです。メソッドをコンストラクタとして定義することはできません。コンストラクタ内でメソッドを呼び出すことはできますが、それでは問題は解決しません。

ngOnInitで一度だけ割り当てられる、本質的に不変のプロパティに対してreadonlyを使えるようにするには?

回答と結論:コンストラクタは好きなように使ってください。必要であれば、readonlyプロパティもそこに置いて構いません。

また、サンドボックスや少なくともいくつかのコードを提供することを検討してください。そうすれば、あなたのコードとニーズの両方に適した回答を作成することができます。

回答 #2

そこではメソッドをコンストラクターとしてマークすることはできません。そのための構文は存在しません。readonly はコンパイル時のチェックにすぎませんが、any への型アサーションを使用して、型安全でない方法で任意の public/private プロパティにアクセスすることで破ることができます。また、マップドタイプを使用して型をミュータブルにすることもできますが、これは public プロパティに対してのみ機能します。

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

関連記事