typescriptにクラス定数を実装する方法は?


430

TypeScriptでは、constキーワードを使用してクラスプロパティを宣言することはできません。これを行うと、「クラスメンバーは 'const'キーワードを持つことができません。」というエラーがコンパイラーに発生します。

プロパティを変更してはいけないことをコードで明確に示す必要があることに気づきました。宣言されたプロパティに新しい値を割り当てようとすると、IDEまたはコンパイラでエラーが発生します。どうやってこれを達成するのですか?

私は現在読み取り専用プロパティを使用していますが、Typescript(およびJavaScript)を初めて使用するので、もっと良い方法があるかどうか疑問に思います。

get MY_CONSTANT():number {return 10};

typescript 1.8を使用しています。提案?

PS:私は現在typescript 2.0.3を使用しているので、Davidの回答を受け入れました

回答:


652

TypeScript 2.0にはreadonly修飾子があります。

class MyClass {
    readonly myReadOnlyProperty = 1;

    myMethod() {
        console.log(this.myReadOnlyProperty);
        this.myReadOnlyProperty = 5; // error, readonly
    }
}

new MyClass().myReadOnlyProperty = 5; // error, readonly

コンストラクタでの割り当てを許可するため、これは厳密には定数ではありませんが、大した問題ではない可能性があります。

代替ソリューション

別の方法としては、次のstaticキーワードを使用しますreadonly

class MyClass {
    static readonly myReadOnlyProperty = 1;

    constructor() {
        MyClass.myReadOnlyProperty = 5; // error, readonly
    }

    myMethod() {
        console.log(MyClass.myReadOnlyProperty);
        MyClass.myReadOnlyProperty = 5; // error, readonly
    }
}

MyClass.myReadOnlyProperty = 5; // error, readonly

これには、コンストラクタで割り当てられず、1つの場所にしか存在しないという利点があります。


31
クラスの外からのプロパティにアクセスするには、追加する必要がありますexport前に、キーワードをclassだけでなく、public staticreadonlyのキーワード。こちらをご覧ください:stackoverflow.com/a/22993349
cbros2008

質問。クラス自体の内部でreadOnlyプロパティを使用するためにクラス名が必要な理由は無知でしたか?'MyClass.myReadonlyProperty'
Saiyaff Farouk

@SaiyaffFarouk私があなたの質問を理解した場合、答えは静的プロパティがクラスのインスタンスではなくクラスの一部として存在するということです。したがって、クラスインスタンスを含む変数ではなく、クラス名を使用してそれらにアクセスします。
JeffryHouser 2017

1
export(外部モジュール)およびpublicキーワードは、この問題/解答には無関係ですが、明示の話題に、私は個人的にキーワードが存在しない場合にメンバーがパブリックであることを伝えるために非常に簡単にそれを見つけます。私はその理由でそれを気にしないでください、そしてそれはより多くのノイズを加えて、そして不必要なタイピングなのでです。また、としてマークされたものから、公共のメンバーがより明確になりprivateprotected。とにかく、ちょうど私の意見:)
デビッドシャーレット

匿名クラスはどうですか?static readonly myReadOnlyPropertyクラスが宣言されているときにアクセスする方法に関するアイデアはありexport default class { ... }ますか?this.myVar、self.myVar、static、defaultを試してみました...動作しません...(編集:default.myVarが解決策のようですが、タイプエラーが発生します)
Alcalyn

67

定数はクラスの外で宣言し、クラス内で使用できます。それ以外の場合、getプロパティは素晴らしい回避策です

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}

6
ありがとう。移植性がなく(モデルでは定数は実際にはクラスの一部ではない)、情報をより大きなスコープにリークするため、この実装について心配していますが、実際の定数であるという利点があるので、警報ベルを鳴らさずに変更できます。
BeetleJuice 2016年

1
私は懸念を理解し、getあなたの場合にプロパティの使用が非常に適切であると思います
j3ff '17

3
angular.io/docs/ts/latest/guide/style-guide.htmlごとに、大文字の代わりにキャメルケースを使用してください。定数の大文字はお勧めしません。
Vadim Kirilchuk 2017年

12
TypeScriptスタイルガイドではなく、角度スタイルガイド。TypeScriptに関する質問でした
VeldMuijz

4
@Esko各ファイルはモジュールであるため、typescriptではconstはファイルに限定されていると思います。外部からアクセスできるようにするには、で宣言しexport constてから、別のファイルからインポートする必要があります。しかし、テストはかなり簡単でしょう。constを1つのファイルで宣言し、エクスポート/インポートなしで別のファイルで使用するか、ブラウザコンソールから使用してみてください。
BeetleJuice


11

Angular 2は、不透明定数と呼ばれる非常に優れた機能を提供します。クラスを作成し、不透明な定数を使用してすべての定数を定義します。

import { OpaqueToken } from "@angular/core";

export let APP_CONFIG = new OpaqueToken("my.config");

export interface MyAppConfig {
    apiEndpoint: string;
}

export const AppConfig: MyAppConfig = {    
    apiEndpoint: "http://localhost:8080/api/"    
};

app.module.tsのプロバイダーに挿入します

すべてのコンポーネントで使用できます。

Angular 4の編集:

Angular 4では、新しい概念は注入トークンであり、不透明トークンはAngular 4で非推奨です。

インジェクショントークン不透明トークンの上に機能を追加します。これにより、TypeScriptジェネリックスとインジェクショントークンを介してトークンにタイプ情報をアタッチでき、@ Injectを追加する必要がなくなります。

コード例

Angular 2の不透明トークンの使用

const API_URL = new OpaqueToken('apiUrl'); //no Type Check


providers: [
  {
    provide: DataService,
    useFactory: (http, apiUrl) => {
      // create data service
    },
    deps: [
      Http,
      new Inject(API_URL) //notice the new Inject
    ]
  }
]

Angular 4インジェクショントークンの使用

const API_URL = new InjectionToken<string>('apiUrl'); // generic defines return value of injector


providers: [
  {
    provide: DataService,
    useFactory: (http, apiUrl) => {
      // create data service
    },
    deps: [
      Http,
      API_URL // no `new Inject()` needed!
    ]
  }
]

インジェクショントークンは、不透明トークンの上に論理的に設計されており、不透明トークンはAngular 4で廃止されました。


6
一を足す。Angularは13歳のティーンエイジャーと同じくらい安定しています。彼らはそれらをリリースしてから数か月後に廃止予定の機能を取得します。ささいなこと。
Stavm

1
マイナス1。この質問はAngularとは関係ありません。TypeScriptソリューションを要求しています。
Ben Nieting 2017年

4

宣言する必要がある定数でreadOnly修飾子を使用するか、クラス外で定数を宣言して、get演算子を使用して必要なクラスでのみそれを具体的に使用することができます。


1

これにはreadonly修飾子を使用できます。オブジェクトのreadonly初期化中にのみ割り当てることができるオブジェクトプロパティ。

クラスの例:

class Circle {
  readonly radius: number;

  constructor(radius: number) {
    this.radius = radius;
  }

  get area() {
    return Math.PI * this.radius * 2;
  }
}

const circle = new Circle(12);
circle.radius = 12; // Cannot assign to 'radius' because it is a read-only property.

オブジェクトリテラルの例:

type Rectangle = {
  readonly height: number;
  readonly width: number;
};

const square: Rectangle = { height: 1, width: 2 };
square.height = 5 // Cannot assign to 'height' because it is a read-only property

また、readonly修飾子は純粋にタイプスクリプトコンストラクトであり、TSがJSにコンパイルされると、コンストラクトはコンパイルされたJSに存在しないことも知っておく価値があります。読み取り専用のプロパティを変更すると、TSコンパイラは警告を表示します(有効なJSです)。


-2

私にとって、以前の答えはどれもうまくいきません。静的クラスを列挙型に変換する必要がありました。このような:

export enum MyConstants {
  MyFirstConstant = 'MyFirstConstant',
  MySecondConstant = 'MySecondConstant'
}

次に、私のコンポーネントに、他の回答で提案されているように新しいプロパティを追加します

export class MyComponent {
public MY_CONTANTS = MyConstans;
constructor() { }
}

次に、私のコンポーネントのテンプレートでこのように使用します

<div [myDirective]="MY_CONTANTS.MyFirstConstant"> </div>

編集:申し訳ありません。私の問題はOPの問題とは異なりました。他の人が私と同じ問題を抱えている場合は、これをここに残します。


enumを使用して定数を保存することは、どの言語でも良い習慣ではありません。
Sangimed

これは、現在利用可能なソリューションに最適なソリューションです。enumを使用しない方がいいのはわかっていますが、Angularを使用すると、バインド可能な定数を持つのに最もクリーンな方法になります。
Janne Harju
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.