Private Class Fields
3.8ではprivateフィールドが追加されました。これはサブクラスを含め、フィールドを定義しているクラスの外側からは
アクセスできないようにするクラスフィールドの宣言方法です。
例えば、以下のPersonクラスでは、どのクラスのインスタンスからも
firstName、lastName、あるいはprefixを読み取ることはできません。
// よくある質問は、"なぜクラスフィールドの'private'キーワードよりもこちらを使うのか?"
というものです。
では、3.8以前のTypeScriptでのふるまいと比較してみましょう。
class Person {
#firstName: string;
#lastName: string;
#prefix: string;
constructor(firstName: string, lastName: string, prefix: string) {
this.#firstName = firstName;
this.#lastName = lastName;
this.#prefix = prefix;
}
greet() {
// アイスランドでは[prefix] [lastname]の代わりにフルネームを用いることが好ましいです
// https://www.w3.org/International/questions/qa-personal-names#patronymic
if (navigator.languages[0] === "is") {
console.log(`Góðan dag, ${this.#firstName} ${this.#lastName}`);
} else {
console.log(`Hello, ${this.#prefix} ${this.#lastName}`);
}
}
}
let jeremy = new Person("Jeremy", "Bearimy", "Mr");
// このクラスの外からは、privateフィールドにアクセスできません:
// 例えば、これは動作しません:
console.log(jeremy.#lastName);
// これも動作しません:
console.log("Person's last name:", jeremy["#lastName"]);
// privateキーワードのTypeScriptの参照は型レベルでしか存在しないので
型レベルまでしか信用できません。
一方で、privateフィールドは近いうちにJavaScript言語の一部となるので
そうなればコードの可視性をより強く保証できるようになります。
TypeScriptの`private`フィールドキーワードを廃止する予定はないので、
既存のコードは引き続き動作します。今では、`private`キーワードの代わりに
よりJavaScriptに近いコードを書くこともできるようになりました。
クラスフィールドについての詳細はtc39の提案
https://github.com/tc39/proposal-class-fields/
とベータ版リリースノートを参照してください:
https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields
class Dog {
private _name: string;
constructor(name: string) {
this._name = name;
}
}
let oby = new Dog("Oby");
// ドット記法でのアクセスはできません
oby._name = "Spot";
// しかし、TypeScriptでは抜け道としてブラケット記法を使えてしまいます
oby["_name"] = "Cherny";