TypeScriptでオブジェクトを機能豊富にする:関数プロパティとメソッドの活用術
TypeScriptにおける関数プロパティとメソッドの比較
共通点
- 型注釈を使用して型安全性を担保できる
- オブジェクトに対して機能を提供する
- オブジェクトのプロパティとして定義される関数
相違点
項目 | 関数プロパティ | メソッド | 備考 |
---|---|---|---|
定義方法 | propertyName: (parameterType) => returnType | methodName(parameterType): returnType | 省略記法も可能 |
型注釈 | 必須 | 任意 | 推論可能 |
this キーワード | 使用不可 | 使用可能 | オブジェクトへのアクセスが可能 |
静的呼び出し | 可能 | 不可 | オブジェクト生成前に呼び出し可能 |
継承 | 親クラスから継承可能 | 親クラスから継承可能 | オーバーライド可能 |
例
class Person {
// 関数プロパティ
greet: (name: string) => string = (name) => `Hello, ${name}!`;
// メソッド
introduce() {
console.log(`My name is ${this.name}.`);
}
}
const person = new Person();
console.log(person.greet('Alice')); // Hello, Alice!
person.introduce(); // My name is John.
使い分け
- 静的呼び出しが必要な場合は、メソッドを定義する必要があります。
- オブジェクトの状態に依存した処理や、
this
キーワードへのアクセスが必要な場合は、メソッドが適切です。 - 単純な関数を提供したい場合は、関数プロパティが簡潔で読みやすいです。
関数プロパティとメソッドは、それぞれ異なる特性を持ち、状況に応じて使い分けることが重要です。 型注釈を活用することで、コードの意図を明確化し、型安全性を高めることができます。
class Person {
// 名前
private name: string;
// コンストラクタ
constructor(name: string) {
this.name = name;
}
// 関数プロパティ - 挨拶
greet(this: Person, targetName: string): string {
return `Hello, ${targetName}! My name is ${this.name}.`;
}
// メソッド - 自己紹介
introduce(): void {
console.log(`My name is ${this.name}.`);
}
// 静的メソッド - 年齢に基づいて成人を判定
static isAdult(age: number): boolean {
return age >= 18;
}
}
// オブジェクトの作成
const person = new Person('John Doe');
// 関数プロパティの呼び出し
console.log(person.greet('Alice')); // Hello, Alice! My name is John Doe.
// メソッドの呼び出し
person.introduce(); // My name is John Doe.
// 静的メソッドの呼び出し
console.log(Person.isAdult(17)); // false
console.log(Person.isAdult(20)); // true
解説
Person クラス
name
プロパティ: プライベート変数で、オブジェクトの名前を保持します。constructor
コンストラクタ: オブジェクト生成時に呼び出され、name
プロパティを初期化します。greet
関数プロパティ: オブジェクト自身の名前と挨拶文を含むメッセージを返します。this
キーワードを使用して、オブジェクト自身にアクセスできます。introduce
メソッド: コンソールにオブジェクトの名前を出力します。isAdult
静的メソッド: 引数の年齢が 18 歳以上かどうかを判定し、真偽値を返します。
オブジェクトの作成
関数プロパティの呼び出し
メソッドの呼び出し
Person.isAdult(17)
を呼び出すことで、isAdult
静的メソッドを実行し、17 歳が成人かどうかを判定します (false を返します)。
簡潔なコード記述に適しています。
class Person {
greet = (name: string) => `Hello, ${name}! My name is ${this.name}.`;
introduce = () => console.log(`My name is ${this.name}.`);
}
ゲッターとセッター
プロパティの値をカプセル化し、制御されたアクセスを提供します。
class Person {
private name: string;
get name(): string {
return this.name;
}
set name(newName: string) {
this.name = newName;
}
}
デコレータ
メソッドの動作を拡張するのに役立ちます。
class Person {
@logger
introduce() {
console.log(`My name is ${this.name}.`);
}
}
function logger(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyKey} with args: ${args}`);
originalMethod.apply(this, args);
};
}
ユーティリティ関数
共通処理を関数として定義し、コードの重複を削減できます。
function greet(this: Person, targetName: string): string {
return `Hello, ${targetName}! My name is ${this.name}.`;
}
class Person {
name: string;
introduce() {
console.log(greet(this, 'Alice'));
}
}
インターフェース
関数プロパティやメソッドの型を定義し、コードの整合性を保ちます。
interface Person {
name: string;
greet(targetName: string): string;
introduce(): void;
}
class PersonImpl implements Person {
name: string;
greet(targetName: string): string {
return `Hello, ${targetName}! My name is ${this.name}.`;
}
introduce(): void {
console.log(this.greet('Alice'));
}
}
これらの代替方法は、状況に応じて使い分けることで、コードの可読性、保守性、再利用性を向上させることができます。
- 関数プロパティとメソッドは基本的な方法ですが、状況に応じてアロー関数、ゲッター/セッター、デコレータ、ユーティリティ関数、インターフェースなどを検討することで、より柔軟で洗練されたコードを書くことができます。
typescript