上級TypeScript開発者向け: getとsetの深い理解
TypeScriptでは、get
とset
アクセサを使用して、プロパティの読み書きを制御できます。これは、データの検証や、その他の処理をプロパティのアクセスに関連付ける場合に役立ちます。
get
アクセサは、プロパティの値を取得するために呼び出されます。以下に例を示します。
class Person {
private _name: string;
get name(): string {
return this._name;
}
constructor(name: string) {
this._name = name;
}
}
const person = new Person("John Doe");
console.log(person.name); // "John Doe" が出力されます
この例では、name
プロパティはプライベート変数_name
をラップしています。get
アクセサは、_name
変数の値を返すために使用されます。
class Person {
private _name: string;
get name(): string {
return this._name;
}
set name(newName: string) {
if (newName.length < 2) {
throw new Error("名前は2文字以上必要です");
}
this._name = newName;
}
constructor(name: string) {
this._name = name;
}
}
const person = new Person("John Doe");
person.name = "Jane Doe"; // 問題なく設定できます
person.name = ""; // エラーが発生します: "名前は2文字以上必要です"
この例では、name
プロパティを設定する前に、名前の長さが2文字以上であることを検証するためにset
アクセサを使用しています。
getとsetアクセサの利点
- データの検証
- 副作用の実行
- プロパティの読み書きを制御
- アクセサは関数であるため、パフォーマンスのオーバーヘッドが発生する可能性があります。
- 複雑なロジックを記述すると、コードの読みやすさが低下する可能性があります。
get
とset
アクセサは、プロパティの読み書きを制御するための強力なツールです。データの検証や、その他の処理をプロパティのアクセスに関連付ける場合に役立ちます。ただし、アクセサは慎重に使用し、コードの読みやすさを保つように注意する必要があります。
// Personクラス
class Person {
private _name: string;
get name(): string {
return this._name;
}
set name(newName: string) {
if (newName.length < 2) {
throw new Error("名前は2文字以上必要です");
}
this._name = newName;
}
constructor(name: string) {
this._name = name;
}
}
// 使用例
const person = new Person("John Doe");
console.log(person.name); // "John Doe" が出力されます
person.name = "Jane Doe"; // 問題なく設定できます
person.name = ""; // エラーが発生します: "名前は2文字以上必要です"
// 年齢プロパティ
class Person {
private _age: number;
get age(): number {
return this._age;
}
set age(newAge: number) {
if (newAge < 0) {
throw new Error("年齢は0以上である必要があります");
}
this._age = newAge;
}
constructor(name: string, age: number) {
this._name = name;
this._age = age;
}
}
// 使用例
const person = new Person("John Doe", 30);
console.log(person.age); // 30 が出力されます
person.age = 31; // 問題なく設定できます
person.age = -1; // エラーが発生します: "年齢は0以上である必要があります"
このサンプルコードは、get
とset
アクセサを使用して、プロパティの読み書きを制御する方法を示しています。
これらのサンプルコードは、get
とset
アクセサのさまざまな使用方法を理解するのに役立ちます。
TypeScriptにおけるgetとsetの代替方法
プライベート変数
最も簡単な方法は、プロパティをプライベート変数として宣言し、公開メソッドを使用してアクセスすることです。以下に例を示します。
class Person {
private _name: string;
constructor(name: string) {
this._name = name;
}
getName(): string {
return this._name;
}
setName(newName: string): void {
this._name = newName;
}
}
const person = new Person("John Doe");
console.log(person.getName()); // "John Doe" が出力されます
person.setName("Jane Doe");
console.log(person.getName()); // "Jane Doe" が出力されます
この方法では、_name
変数はクラス内にのみ公開されます。外部コードは、getName()
とsetName()
メソッドを使用してプロパティにアクセスする必要があります。
プロパティデコレータ
get
とset
アクセサの代わりに、プロパティデコレータを使用して、プロパティの読み書きを制御することもできます。以下に例を示します。
function getNameDecorator(target: any, propertyKey: string): void {
// ここにロジックを記述
const getter = function(this: any): string {
return this[propertyKey];
};
const setter = function(this: any, newValue: string): void {
this[propertyKey] = newValue;
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
});
}
class Person {
@getNameDecorator
private _name: string;
constructor(name: string) {
this._name = name;
}
}
const person = new Person("John Doe");
console.log(person.name); // "John Doe" が出力されます
person.name = "Jane Doe";
console.log(person.name); // "Jane Doe" が出力されます
この方法では、getNameDecorator
デコレータを使用して、name
プロパティの読み書きを制御しています。デコレータ内では、get
とset
アクセサを定義して、プロパティのアクセスに関連する処理を記述することができます。
クラスフィールド
TypeScript 3.7以降では、クラスフィールドを使用して、プロパティの読み書きを制御することができます。以下に例を示します。
class Person {
#name: string;
constructor(name: string) {
this.#name = name;
}
get name(): string {
return this.#name;
}
set name(newName: string): void {
this.#name = newName;
}
}
const person = new Person("John Doe");
console.log(person.name); // "John Doe" が出力されます
person.name = "Jane Doe";
console.log(person.name); // "Jane Doe" が出力されます
この方法では、#name
フィールドを使用して、プロパティをプライベート変数として宣言しています。外部コードは、get
とset
アクセサを使用してプロパティにアクセスする必要があります。
- プライベート変数のみで十分な場合は、最も簡単な方法です。
- プロパティの読み書きにロジックを追加する必要がある場合は、
get
とset
アクセサまたはプロパティデコレータを使用する必要があります。 - TypeScript 3.7以降を使用している場合は、クラスフィールドを使用することもできます。
それぞれの方法のメリットとデメリットを理解し、状況に合った方法を選択することが重要です。
typescript