TypeScriptでクラスを使用する際、プロパティやメソッドのデフォルト値を設定することは、コードの安定性や柔軟性を高めるための重要な技術です。デフォルト値を設定することで、クラスを使用する際に必ずしもすべての値を初期化する必要がなく、簡潔なコードを書くことが可能になります。特に、複数のオプションを持つコンストラクタや、柔軟なメソッド呼び出しをサポートするためにはデフォルト値が欠かせません。本記事では、TypeScriptにおけるデフォルト値の設定方法とその活用法について、具体例を交えながら解説していきます。
TypeScriptにおけるデフォルト値の重要性
TypeScriptでデフォルト値を設定することは、コードの保守性や可読性を向上させるだけでなく、バグの防止にも役立ちます。特に大規模なプロジェクトでは、すべての引数やプロパティに値を明示的に設定することが難しくなるため、デフォルト値を設定しておくと、クラスやメソッドの使用がより簡単かつエラーが少ないものになります。
デフォルト値の設定は次のような利点があります。
コードの簡潔化
開発者が意図しない値の設定を防ぎ、コードが読みやすくなります。また、メソッドやクラスの呼び出し時に冗長な引数を減らし、シンプルなコードを実現します。
柔軟性の向上
デフォルト値を設定することで、すべてのプロパティやメソッド引数を必ず指定する必要がなくなり、柔軟な設計が可能です。特に、オプションパラメータや設定可能なプロパティが多いクラスでは、この機能が非常に有用です。
バグの防止
デフォルト値を持たない変数やプロパティは、未定義のまま使用される可能性がありますが、デフォルト値を設定することで、これらのリスクを大幅に減少させることができます。
クラスのプロパティにデフォルト値を設定する方法
TypeScriptでクラスのプロパティにデフォルト値を設定するのは非常に簡単です。クラス定義内でプロパティに対して初期値を割り当てるだけで、自動的にそのプロパティにデフォルト値が設定されます。これは、オブジェクトのインスタンス化時に値を渡さなかった場合でも、そのプロパティが未定義になることを防ぎます。
基本的な構文
以下の例では、Person
クラスのプロパティname
とage
にデフォルト値を設定しています。
class Person {
name: string = "John Doe";
age: number = 30;
}
const person1 = new Person();
console.log(person1.name); // "John Doe"
console.log(person1.age); // 30
このコードでは、Person
クラスのインスタンスperson1
を作成する際に、name
とage
に何も指定しなくても、デフォルト値が適用されます。これにより、インスタンスを初期化する際に最低限の設定で済むため、コードがよりシンプルになります。
コンストラクタとデフォルト値の併用
クラスコンストラクタで渡された引数を使用しつつ、デフォルト値を保持することも可能です。コンストラクタ内でプロパティに渡された値が存在しない場合、デフォルト値が利用されます。
class Person {
name: string;
age: number;
constructor(name: string = "John Doe", age: number = 30) {
this.name = name;
this.age = age;
}
}
const person2 = new Person("Alice");
console.log(person2.name); // "Alice"
console.log(person2.age); // 30
ここでは、name
には引数として”John Doe”以外の値を渡していますが、age
は指定されていないため、デフォルト値の30が適用されます。このように、デフォルト値を設定することで、クラスを柔軟に使用できるようになります。
メソッド引数にデフォルト値を設定する方法
TypeScriptでは、クラス内のメソッドに引数のデフォルト値を設定することも簡単です。デフォルト値を指定すると、メソッドを呼び出す際にその引数が省略された場合、自動的に指定したデフォルト値が使われるようになります。これにより、コードがより柔軟になり、冗長な引数の指定を避けることができます。
基本的な構文
以下の例では、greet
というメソッドにgreeting
引数を設定し、そのデフォルト値を "Hello"
にしています。
class Greeter {
greet(greeting: string = "Hello"): void {
console.log(greeting);
}
}
const greeter = new Greeter();
greeter.greet(); // "Hello"
greeter.greet("Hi there"); // "Hi there"
このコードでは、greet
メソッドのgreeting
引数に値が渡されない場合、自動的に "Hello"
というデフォルト値が使用されます。引数を明示的に渡した場合は、その値が優先されます。
複数引数にデフォルト値を設定する
TypeScriptでは、複数の引数にデフォルト値を設定することができます。ただし、デフォルト値を持つ引数は、その後に続く引数があっても省略することができるため、順序にも注意が必要です。
class Calculator {
calculate(a: number = 1, b: number = 2, operation: string = "add"): number {
if (operation === "add") {
return a + b;
} else if (operation === "subtract") {
return a - b;
}
return 0;
}
}
const calculator = new Calculator();
console.log(calculator.calculate()); // 3 (1 + 2)
console.log(calculator.calculate(5)); // 7 (5 + 2)
console.log(calculator.calculate(5, 3, "subtract")); // 2 (5 - 3)
この例では、3つの引数にデフォルト値を設定しています。デフォルト値が適用されるのは、引数が省略された場合のみです。operation
に "subtract"
を指定することで、引き算も可能となっています。
デフォルト値とオプショナル引数の違い
デフォルト値を持つ引数と、TypeScriptでサポートされているオプショナル引数(?
で定義する)とは異なります。オプショナル引数は省略可能な引数で、値が渡されなければ undefined
になります。一方、デフォルト値を持つ引数は、値が省略された場合にそのデフォルト値が使用されます。
class Example {
printMessage(message?: string): void {
console.log(message || "Default message");
}
}
const example = new Example();
example.printMessage(); // "Default message"
example.printMessage("Hello"); // "Hello"
この例では、オプショナル引数のmessage
が省略された場合、undefined
ではなく "Default message"
を表示するようにしています。このように、デフォルト値とオプショナル引数の使い分けによって、メソッドの設計に柔軟性を持たせることができます。
デフォルト値の使用例:クラスプロパティ編
TypeScriptでクラスプロパティにデフォルト値を設定することで、クラスインスタンスの初期化時にプロパティの初期値を省略しても動作するようにすることができます。これは、複数のインスタンスを作成する際に、異なるプロパティを持つ場合でも、共通のデフォルト設定を保持するのに役立ちます。
例1: ユーザークラスのプロパティにデフォルト値を設定
次に示す例では、User
クラスのname
、age
、isAdmin
というプロパティにデフォルト値を設定しています。
class User {
name: string = "Unknown";
age: number = 18;
isAdmin: boolean = false;
}
const user1 = new User();
console.log(user1.name); // "Unknown"
console.log(user1.age); // 18
console.log(user1.isAdmin); // false
const user2 = new User();
user2.name = "Alice";
console.log(user2.name); // "Alice"
この例では、user1
はデフォルト値を使って初期化されますが、user2
ではname
プロパティが上書きされて、 "Alice"
となっています。age
やisAdmin
のような他のプロパティはそのままデフォルト値が使われます。
例2: コンストラクタでデフォルト値を上書き可能にする
プロパティにデフォルト値を設定するだけでなく、コンストラクタを使ってそれらの値を変更できる柔軟性を持たせることもできます。以下の例では、Product
クラスのプロパティに対して、コンストラクタで任意に値を渡せるようにしています。
class Product {
name: string;
price: number = 100;
inStock: boolean = true;
constructor(name: string = "Unknown Product", price?: number, inStock?: boolean) {
this.name = name;
if (price !== undefined) {
this.price = price;
}
if (inStock !== undefined) {
this.inStock = inStock;
}
}
}
const defaultProduct = new Product();
console.log(defaultProduct.name); // "Unknown Product"
console.log(defaultProduct.price); // 100
console.log(defaultProduct.inStock); // true
const customProduct = new Product("Laptop", 1500, false);
console.log(customProduct.name); // "Laptop"
console.log(customProduct.price); // 1500
console.log(customProduct.inStock); // false
この例では、name
のデフォルト値として "Unknown Product"
を設定していますが、customProduct
のインスタンス作成時にカスタムの値を渡すことができるため、柔軟にインスタンスを生成できます。
クラスプロパティにデフォルト値を設定するメリット
プロパティにデフォルト値を設定することは以下のような利点をもたらします。
コードの可読性とメンテナンス性の向上
デフォルト値があることで、クラスの利用者はそのプロパティの標準的な動作を理解しやすくなり、コードのメンテナンスが容易になります。さらに、クラス定義内に値が明示されているため、他の開発者もプロパティの目的を直感的に理解できます。
インスタンス化時のエラー防止
すべてのプロパティに必ずしも値を渡す必要がないため、コンストラクタを複雑にすることなくクラスインスタンスを柔軟に生成できます。また、誤って未定義のプロパティにアクセスしてしまうリスクも軽減されます。
このように、クラスのプロパティにデフォルト値を設定することで、コードの安定性を保ちながら柔軟な設計が可能になります。
デフォルト値の使用例:メソッド引数編
TypeScriptでは、メソッドの引数にもデフォルト値を設定することが可能です。これにより、メソッド呼び出し時に引数を省略しても、デフォルトの動作を保証することができます。デフォルト値を設定することで、メソッドの柔軟性が向上し、引数を省略したい場合でも簡単に利用できるようになります。
例1: デフォルト値を使った簡単なメソッド
次の例では、introduce
というメソッドに2つの引数name
とgreeting
を持たせています。greeting
にはデフォルト値 "Hello"
を設定しているため、引数を渡さない場合でも挨拶が表示されます。
class Person {
introduce(name: string, greeting: string = "Hello"): string {
return `${greeting}, my name is ${name}.`;
}
}
const person = new Person();
console.log(person.introduce("Alice")); // "Hello, my name is Alice."
console.log(person.introduce("Bob", "Hi there")); // "Hi there, my name is Bob."
この例では、introduce
メソッドを呼び出す際にgreeting
を省略すると、デフォルト値の "Hello"
が使われます。一方、greeting
を指定すればその値が使用されます。
例2: 複数の引数にデフォルト値を設定する
複数の引数にデフォルト値を設定する場合、それぞれの引数に対して省略可能なデフォルト値を設定できます。次の例では、add
メソッドにデフォルト値を設定し、足し算を行うメソッドを柔軟にしています。
class Calculator {
add(a: number = 0, b: number = 0): number {
return a + b;
}
}
const calculator = new Calculator();
console.log(calculator.add()); // 0 (デフォルト値: 0 + 0)
console.log(calculator.add(5)); // 5 (5 + 0)
console.log(calculator.add(3, 7)); // 10 (3 + 7)
この例では、2つの引数a
とb
にデフォルト値を設定しています。どちらの引数も省略可能で、指定しなければ0が使用されます。このように、メソッドに対して柔軟な呼び出し方法を提供することができます。
例3: コンストラクタメソッドでのデフォルト値の利用
コンストラクタにおいても、引数にデフォルト値を設定することで、クラスのインスタンスを作成する際の利便性が高まります。次の例では、Rectangle
クラスのコンストラクタにデフォルト値を設定し、オプションで幅と高さを指定できるようにしています。
class Rectangle {
width: number;
height: number;
constructor(width: number = 10, height: number = 5) {
this.width = width;
this.height = height;
}
area(): number {
return this.width * this.height;
}
}
const defaultRectangle = new Rectangle();
console.log(defaultRectangle.area()); // 50 (10 * 5)
const customRectangle = new Rectangle(20, 15);
console.log(customRectangle.area()); // 300 (20 * 15)
この例では、Rectangle
クラスのコンストラクタで、width
とheight
にデフォルト値を設定しています。デフォルトの値が使用される場合、幅10、高さ5の長方形が生成され、指定があればそれに応じた値が適用されます。
メソッド引数にデフォルト値を設定するメリット
メソッド引数にデフォルト値を設定することには、いくつかの重要な利点があります。
柔軟性の向上
引数が多いメソッドでも、デフォルト値を設定することで、呼び出し時にすべての引数を指定する必要がなくなり、柔軟に利用できます。省略した引数には自動的にデフォルト値が使われるため、簡潔なコードが書けます。
エラーハンドリングの簡素化
引数が省略された場合にundefined
やnull
に依存するのではなく、デフォルト値があることで明示的に動作を制御でき、エラーハンドリングの手間を減らすことができます。
このように、メソッド引数にデフォルト値を設定することで、コードの柔軟性や保守性が向上し、より効率的なプログラミングが可能になります。
デフォルト値設定の際の注意点とベストプラクティス
TypeScriptでデフォルト値を設定することは非常に便利ですが、その利用にはいくつかの注意点とベストプラクティスがあります。デフォルト値を効果的に使うことで、コードの保守性や可読性を向上させ、予期しないバグを防ぐことができます。
注意点1: デフォルト値の順序
デフォルト値を持つ引数は、デフォルト値を持たない引数の後に配置する必要があります。これは、TypeScriptが関数呼び出し時に引数の位置に基づいて値を渡すため、デフォルト値を持つ引数が先に来てしまうと、混乱を引き起こす可能性があるからです。
function example(a: number, b: number = 10) {
return a + b;
}
console.log(example(5)); // 15 (a = 5, b = 10)
この場合、b
はデフォルト値を持つため省略可能ですが、デフォルト値を持たない引数a
が前に来ているため、関数呼び出し時に問題が発生しません。もし逆の順序にすると、関数呼び出しが曖昧になります。
注意点2: `undefined`でデフォルト値が使われる挙動
デフォルト値は、引数がundefined
として渡された場合にも適用されます。しかし、null
が渡された場合はデフォルト値は使用されず、明示的にnull
が引数の値として設定されます。この挙動を理解しておくことが重要です。
function greet(name: string = "Guest") {
return `Hello, ${name}`;
}
console.log(greet(undefined)); // "Hello, Guest"
console.log(greet(null)); // "Hello, null"
この例では、undefined
が渡された場合はデフォルト値が使用されますが、null
が渡された場合はそのままnull
が適用されます。
ベストプラクティス1: デフォルト値を過度に多用しない
デフォルト値は便利ですが、すべてのプロパティや引数にデフォルト値を設定するのは避けるべきです。あまりに多くのデフォルト値を設定すると、コードが複雑になり、逆に予期しない動作を引き起こす可能性があります。デフォルト値は、開発者が設定しなくても適切な値が推測できる場面に限定して使うのが良いです。
ベストプラクティス2: デフォルト値の使用は明確に
デフォルト値を設定する際には、クラスやメソッドのドキュメントでその存在を明確にすることが重要です。これにより、他の開発者がそのクラスやメソッドを使用する際に混乱せず、想定通りの動作を理解することができます。コメントやTypeScriptの型定義ファイルにデフォルト値を明記しておくと良いでしょう。
ベストプラクティス3: 単純なデフォルト値を利用する
デフォルト値にはできるだけ単純で予測可能な値を使用しましょう。複雑なオブジェクトや関数をデフォルト値に設定すると、予期しない副作用を引き起こすことがあります。単純なリテラル値や基礎的な型を使うことが推奨されます。
class Settings {
theme: string = "light";
notificationsEnabled: boolean = true;
}
このように単純なデフォルト値を設定することで、コードの読みやすさと予測可能な動作を維持することができます。
ベストプラクティス4: 複雑なデフォルト値には関数を使う
デフォルト値に計算や動的な処理が必要な場合は、直接値を設定するのではなく、関数を使ってその場で値を生成する方法が有効です。これにより、コードの可読性を保ちながら、柔軟な処理が可能になります。
class Config {
apiUrl: string;
timeout: number;
constructor(apiUrl: string = "https://api.example.com", timeout: number = Config.defaultTimeout()) {
this.apiUrl = apiUrl;
this.timeout = timeout;
}
static defaultTimeout(): number {
return new Date().getHours() < 18 ? 3000 : 5000;
}
}
このように、複雑なロジックをデフォルト値に持たせる場合は、関数を用いることでコードの整理ができます。
ベストプラクティス5: 型安全性を確保する
デフォルト値を設定する際には、型安全性にも注意しましょう。特に、複雑な型を扱う場合、意図しない型の値がデフォルトとして設定されると、ランタイムエラーの原因になる可能性があります。TypeScriptの型チェックを活用して、安全なデフォルト値を設定することが重要です。
このように、デフォルト値を設定する際の注意点とベストプラクティスを理解しておくことで、TypeScriptのコードがより柔軟で堅牢なものになります。
応用例:オプショナルプロパティとの併用
TypeScriptでは、デフォルト値の設定とオプショナルプロパティ(任意プロパティ)を併用することで、柔軟なクラス設計が可能になります。オプショナルプロパティは、値が指定されない場合でもundefined
となることを許容するため、デフォルト値と組み合わせることでより高度な設定ができます。
オプショナルプロパティとは
オプショナルプロパティは、?
記号を使って指定することで、そのプロパティが必須ではないことを表します。これにより、プロパティが存在しない場合でもエラーが発生しません。デフォルト値と異なり、オプショナルプロパティに値が設定されない場合はundefined
になります。
class User {
name?: string;
age?: number;
isAdmin: boolean = false;
}
const user1 = new User();
console.log(user1.name); // undefined
console.log(user1.isAdmin); // false
この例では、name
とage
はオプショナルプロパティなので、値を設定しなくてもエラーになりません。一方で、isAdmin
にはデフォルト値が設定されているため、インスタンス化時に値がない場合はfalse
が適用されます。
デフォルト値とオプショナルプロパティの組み合わせ
オプショナルプロパティとデフォルト値を組み合わせることで、デフォルト値が設定されていない場合にも適切に動作する柔軟なクラス設計が可能です。例えば、コンストラクタでオプショナルな引数を指定し、デフォルト値がない場合はundefined
をチェックして、必要に応じて値を設定します。
class Product {
name: string;
price: number;
discount?: number;
constructor(name: string = "Unknown", price: number = 100, discount?: number) {
this.name = name;
this.price = price;
this.discount = discount ?? 0; // discountがundefinedなら0を設定
}
finalPrice(): number {
return this.price - this.discount!;
}
}
const product1 = new Product();
console.log(product1.finalPrice()); // 100 (デフォルト値使用、割引なし)
const product2 = new Product("Laptop", 1500, 200);
console.log(product2.finalPrice()); // 1300 (1500 - 200)
この例では、discount
はオプショナルプロパティとして定義されています。コンストラクタ内では、discount
がundefined
であれば、デフォルト値として0を設定しています。これにより、プロパティの有無によって柔軟に動作するクラスを実現しています。
オプショナルプロパティの活用例
次の例では、Settings
クラスでオプショナルプロパティとデフォルト値を組み合わせ、ユーザーが一部の設定だけを指定しても適切に処理されるように設計しています。
class Settings {
theme: string;
notificationsEnabled?: boolean;
constructor(theme: string = "light", notificationsEnabled?: boolean) {
this.theme = theme;
this.notificationsEnabled = notificationsEnabled ?? true; // オプショナルプロパティにデフォルト値を設定
}
showSettings(): string {
return `Theme: ${this.theme}, Notifications: ${this.notificationsEnabled ? "Enabled" : "Disabled"}`;
}
}
const settings1 = new Settings();
console.log(settings1.showSettings()); // "Theme: light, Notifications: Enabled"
const settings2 = new Settings("dark", false);
console.log(settings2.showSettings()); // "Theme: dark, Notifications: Disabled"
この例では、theme
にデフォルト値を設定し、notificationsEnabled
をオプショナルプロパティとして扱っています。notificationsEnabled
がundefined
の場合はデフォルトでtrue
を設定し、それ以外の場合はユーザー指定の値が反映されます。
オプショナルプロパティとデフォルト値を使うメリット
デフォルト値とオプショナルプロパティの併用は、以下の利点をもたらします。
柔軟なクラス設計
必須のプロパティとオプショナルなプロパティを適切に分けることで、複雑な設定やデータ構造を柔軟に扱うことができます。ユーザーが全てのプロパティを指定しなくても、クラスは適切に動作します。
コードの簡潔化
オプショナルプロパティとデフォルト値を使うことで、複雑な初期化ロジックが不要になり、シンプルでメンテナンスしやすいコードを書くことができます。また、開発者は必要なプロパティだけを指定できるため、コードの記述量を減らせます。
未定義値のハンドリングが容易
オプショナルプロパティに対してundefined
チェックを行いながらデフォルト値を設定することで、未定義の値を適切に処理し、予期せぬエラーの発生を防ぎます。
このように、オプショナルプロパティとデフォルト値を適切に組み合わせることで、TypeScriptでより柔軟かつ堅牢なクラス設計が可能になります。
デフォルト値を持つクラスのテスト方法
TypeScriptでデフォルト値を持つクラスやメソッドを設計する際、正しく動作することを確認するために、適切なテストを行うことが非常に重要です。特にデフォルト値を設定したプロパティや引数に対する挙動が正しいかどうかを検証するためのテストは、コードの信頼性を向上させるための基本です。
このセクションでは、デフォルト値を持つクラスやメソッドをテストする具体的な方法を紹介します。
ユニットテストの重要性
デフォルト値を持つクラスやメソッドに対するユニットテストを行うことで、次のような利点があります。
- デフォルト値が意図通りに適用されているかを確認できる。
- デフォルト値が上書きされた場合、正しい結果が得られるかを検証できる。
- メソッドやクラスの予期しない動作を未然に防ぐことができる。
Jestを使ったテスト例
JavaScriptやTypeScriptでのテストには、一般的にJestなどのテストフレームワークが使用されます。以下の例では、デフォルト値を持つクラスやメソッドに対する基本的なテストケースを紹介します。
// Product.ts
class Product {
name: string;
price: number;
discount?: number;
constructor(name: string = "Unknown", price: number = 100, discount?: number) {
this.name = name;
this.price = price;
this.discount = discount ?? 0;
}
finalPrice(): number {
return this.price - this.discount!;
}
}
export default Product;
次に、このProduct
クラスに対するテストケースを作成します。
// Product.test.ts
import Product from './Product';
describe('Product class tests', () => {
test('should apply default values when no arguments are provided', () => {
const product = new Product();
expect(product.name).toBe('Unknown');
expect(product.price).toBe(100);
expect(product.discount).toBe(0);
expect(product.finalPrice()).toBe(100);
});
test('should use provided values instead of default ones', () => {
const product = new Product('Laptop', 1500, 200);
expect(product.name).toBe('Laptop');
expect(product.price).toBe(1500);
expect(product.discount).toBe(200);
expect(product.finalPrice()).toBe(1300);
});
test('should apply default discount when only name and price are provided', () => {
const product = new Product('Phone', 800);
expect(product.name).toBe('Phone');
expect(product.price).toBe(800);
expect(product.discount).toBe(0);
expect(product.finalPrice()).toBe(800);
});
});
テストケースの詳細
上記のテストコードでは、デフォルト値の挙動を検証するためのいくつかのテストケースを作成しています。
デフォルト値が適用されるかを確認するテスト
最初のテストケースでは、Product
クラスに引数を与えずにインスタンス化した場合、デフォルト値が適切に適用されるかを確認しています。この場合、name
は "Unknown"
、price
は 100
、そしてdiscount
は 0
というデフォルト値が設定されることを期待しています。
test('should apply default values when no arguments are provided', () => {
const product = new Product();
expect(product.name).toBe('Unknown');
expect(product.price).toBe(100);
expect(product.discount).toBe(0);
expect(product.finalPrice()).toBe(100);
});
提供された引数が正しく適用されるかを確認するテスト
次のテストケースでは、インスタンス作成時にすべての引数を指定した場合、デフォルト値が上書きされ、指定した値が適切に反映されるかを確認しています。
test('should use provided values instead of default ones', () => {
const product = new Product('Laptop', 1500, 200);
expect(product.name).toBe('Laptop');
expect(product.price).toBe(1500);
expect(product.discount).toBe(200);
expect(product.finalPrice()).toBe(1300);
});
一部の引数だけを提供した場合のテスト
最後に、一部の引数だけが渡された場合に、未提供の引数にデフォルト値が適用されるかどうかを確認するテストです。ここではdiscount
に値が指定されていないため、デフォルト値の0
が適用されます。
test('should apply default discount when only name and price are provided', () => {
const product = new Product('Phone', 800);
expect(product.name).toBe('Phone');
expect(product.price).toBe(800);
expect(product.discount).toBe(0);
expect(product.finalPrice()).toBe(800);
});
テストのベストプラクティス
デフォルト値を持つクラスやメソッドをテストする際は、以下のポイントを意識しましょう。
1. すべてのパターンをカバーする
デフォルト値が使用される場合と、指定された値が適用される場合の両方をしっかりとテストし、各パターンで正しい動作を確認します。
2. 異常系のテストも行う
無効な引数が渡された場合や引数が不完全な場合にも、エラーが発生せず期待通りに動作するかをテストすることが重要です。
3. 環境依存の動作に注意する
特定の条件に依存するデフォルト値(たとえば日付やランダムな値)は、テストが安定して動作するようにモックやスタブを活用して制御する必要があります。
これらの方法を用いて、デフォルト値を持つクラスやメソッドを効率的にテストすることで、コードの品質を高めることができます。
演習問題:デフォルト値を活用したクラス設計
ここでは、TypeScriptでデフォルト値を活用したクラス設計の演習問題を紹介します。これにより、実際にコードを作成してデフォルト値の設定方法や、オプショナルプロパティとの組み合わせを学びます。
問題1: クラス`Car`の作成
次の仕様に従って、Car
クラスを作成してください。
- プロパティとして
make
(メーカー)、model
(モデル)、year
(年式)を持つ。 make
にはデフォルト値として"Unknown"
、model
にはデフォルト値として"Generic"
、year
にはデフォルト値として2000
を設定する。- メソッド
displayInfo
を実装し、"Car: make, model (year)"
という形式で車の情報を表示する。 - オプションで、年式を指定できるが、指定されない場合はデフォルト値を適用する。
期待する動作例:
const car1 = new Car();
console.log(car1.displayInfo()); // "Car: Unknown, Generic (2000)"
const car2 = new Car("Toyota", "Corolla", 2021);
console.log(car2.displayInfo()); // "Car: Toyota, Corolla (2021)"
解答例
class Car {
make: string;
model: string;
year: number;
constructor(make: string = "Unknown", model: string = "Generic", year: number = 2000) {
this.make = make;
this.model = model;
this.year = year;
}
displayInfo(): string {
return `Car: ${this.make}, ${this.model} (${this.year})`;
}
}
const car1 = new Car();
console.log(car1.displayInfo()); // "Car: Unknown, Generic (2000)"
const car2 = new Car("Toyota", "Corolla", 2021);
console.log(car2.displayInfo()); // "Car: Toyota, Corolla (2021)"
この例では、Car
クラスに対して、すべての引数にデフォルト値が設定されています。make
とmodel
にデフォルト値を使いながら、特定のインスタンスではこれを上書きすることができます。
問題2: クラス`User`の作成
次に、ユーザー情報を管理するUser
クラスを作成してください。
- プロパティとして
username
(ユーザー名)、email
(メールアドレス)、isAdmin
(管理者フラグ)を持つ。 username
はデフォルトで"guest"
、email
はデフォルトで空文字列""
、isAdmin
はfalse
とする。- メソッド
getUserInfo
を実装し、ユーザー名、メールアドレス、および管理者かどうかの情報を返す。 isAdmin
がtrue
の場合は、"Admin"
、false
の場合は"User"
と表示する。
期待する動作例:
const user1 = new User();
console.log(user1.getUserInfo()); // "guest (User), Email: "
const user2 = new User("john_doe", "john@example.com", true);
console.log(user2.getUserInfo()); // "john_doe (Admin), Email: john@example.com"
解答例
class User {
username: string;
email: string;
isAdmin: boolean;
constructor(username: string = "guest", email: string = "", isAdmin: boolean = false) {
this.username = username;
this.email = email;
this.isAdmin = isAdmin;
}
getUserInfo(): string {
const role = this.isAdmin ? "Admin" : "User";
return `${this.username} (${role}), Email: ${this.email}`;
}
}
const user1 = new User();
console.log(user1.getUserInfo()); // "guest (User), Email: "
const user2 = new User("john_doe", "john@example.com", true);
console.log(user2.getUserInfo()); // "john_doe (Admin), Email: john@example.com"
この例では、User
クラスのプロパティにデフォルト値を設定し、ユーザーが一部の情報しか提供しない場合にも問題なく動作するようになっています。また、isAdmin
のフラグによって役割を表示する柔軟性も持たせています。
問題3: クラス`Order`の作成
最後に、注文情報を管理するOrder
クラスを作成してください。
- プロパティとして
orderId
(注文ID)、amount
(注文金額)、status
(注文状況)を持つ。 orderId
は必須のプロパティで、amount
はデフォルトで0
、status
は"Pending"
というデフォルト値を持つ。- メソッド
getOrderSummary
を実装し、"Order ID: orderId, Amount: amount, Status: status"
という形式で注文情報を表示する。
期待する動作例:
const order1 = new Order("12345");
console.log(order1.getOrderSummary()); // "Order ID: 12345, Amount: 0, Status: Pending"
const order2 = new Order("67890", 250, "Shipped");
console.log(order2.getOrderSummary()); // "Order ID: 67890, Amount: 250, Status: Shipped"
解答例
class Order {
orderId: string;
amount: number;
status: string;
constructor(orderId: string, amount: number = 0, status: string = "Pending") {
this.orderId = orderId;
this.amount = amount;
this.status = status;
}
getOrderSummary(): string {
return `Order ID: ${this.orderId}, Amount: ${this.amount}, Status: ${this.status}`;
}
}
const order1 = new Order("12345");
console.log(order1.getOrderSummary()); // "Order ID: 12345, Amount: 0, Status: Pending"
const order2 = new Order("67890", 250, "Shipped");
console.log(order2.getOrderSummary()); // "Order ID: 67890, Amount: 250, Status: Shipped"
この問題では、orderId
が必須の引数であり、その他のプロパティにデフォルト値を設定しています。これにより、柔軟かつ簡潔な注文管理が可能になっています。
演習問題のまとめ
これらの演習問題では、TypeScriptでクラスのプロパティやメソッドにデフォルト値を設定する方法を学びました。デフォルト値を使うことで、クラスを柔軟に設計でき、ユーザーにとって使いやすいAPIを提供できます。
まとめ
本記事では、TypeScriptにおけるクラスプロパティやメソッド引数にデフォルト値を設定する方法について解説しました。デフォルト値を設定することで、コードの柔軟性や保守性が向上し、複雑な引数管理をシンプルにすることができます。また、オプショナルプロパティとの組み合わせにより、さらに高度なクラス設計が可能となります。適切にデフォルト値を活用することで、エラーを減らし、予期しない挙動を防ぎ、効率的な開発を実現できるようになります。
コメント