TypeScript インターフェース 必須プロパティ
必須プロパティとオプションプロパティ
- オプションプロパティ: インターフェイスのインスタンスで存在しない可能性があるプロパティです。
- 必須プロパティ: インターフェイスのインスタンスで必ず存在するプロパティです。
必須プロパティの指定
- プロパティ名の後に「!」を付けると、そのプロパティは必須になります。
2つのプロパティのうち少なくとも1つが必須である場合
- 2つのプロパティをオプションにし、その後に「|」演算子を使用して、どちらかのプロパティが必須であることを指定します。
例
interface Person {
name: string;
age?: number;
address?: string;
}
interface Employee extends Person {
department: string;
salary: number;
// 2つのプロパティのうち少なくとも1つが必須
phoneOrEmail: string | string;
}
この例では、Person
インターフェイスのage
とaddress
プロパティはオプションです。Employee
インターフェイスのphoneOrEmail
プロパティは、string
型またはstring
型のどちらか一方の値を持つ必要があります。
TypeScript インターフェースで2つのプロパティのうち少なくとも1つが必須である場合のコード例
基本的な例
interface Person {
name: string;
age?: number; // オプションのプロパティ
address?: string; // オプションのプロパティ
}
interface Employee extends Person {
department: string;
salary: number;
// phoneOrEmailプロパティはstring型またはstring型で、どちらか一方を必ず持つ
phoneOrEmail: string | string;
}
- Employeeインターフェース
Person
インターフェースを継承phoneOrEmail
プロパティは、string
型またはstring
型で、どちらか一方を必ず持つように制約
- Personインターフェース
name
は必須プロパティage
とaddress
はオプションプロパティ
より詳細な例(ディープなオブジェクト)
interface Contact {
email?: string;
phone?: string;
// emailまたはphoneのどちらかは必須
contactInfo: { email: string } | { phone: string };
}
const person1: Contact = {
name: '太郎',
contactInfo: { email: '[email protected]' }
};
const person2: Contact = {
name: '次郎',
contactInfo: { phone: '090-1234-5678' }
};
- Contactインターフェース
contactInfo
プロパティは、email
プロパティを持つオブジェクトかphone
プロパティを持つオブジェクトのどちらか- つまり、
email
またはphone
のどちらかのプロパティは必ず存在する
型エイリアスとユニオン型を組み合わせた例
type EmailContact = { email: string };
type PhoneContact = { phone: string };
type ContactInfo = EmailContact | PhoneContact;
interface Person {
name: string;
contactInfo: ContactInfo;
}
- Personインターフェース
contactInfo
プロパティはContactInfo
型 - ユニオン型
ContactInfo
はEmailContact
またはPhoneContact
のどちらか - 型エイリアス
EmailContact
,PhoneContact
,ContactInfo
を定義
コード例の説明
- オブジェクトリテラル
{ ... }
でオブジェクトを定義します。 - インターフェースの継承
extends
キーワードを使用して、既存のインターフェースから新しいインターフェースを作成できます。 - | (パイプ) 演算子
複数の型を組み合わせる際に使用。この例では、string | string
はstring
型またはstring
型を表します。
重要なポイント
- 型エイリアス
既存の型に別の名前をつけること。 - ユニオン型
複数の型の中から一つを選ぶことができる型。
これらのコード例は、TypeScriptのインターフェースで、複数のプロパティのうち少なくとも1つが必須であるという状況を表現する一般的な方法を示しています。
- TypeScriptの型システムは非常に柔軟で、さまざまなシナリオに対応できます。
- より複雑な条件や複数のプロパティの組み合わせも、ユニオン型やインターフェースの組み合わせで表現できます。
ディープなインターフェースとオプションチェーン
interface ContactInfo {
email?: string;
phone?: string;
}
interface Person {
name: string;
contactInfo: ContactInfo;
}
const person1: Person = {
name: '太郎',
contactInfo: { email: '[email protected]' }
};
// 値の取得(オプションチェーンを使用)
const email = person1.contactInfo?.email;
const phone = person1.contactInfo?.phone;
- 特徴
ContactInfo
インターフェースで、email
とphone
を両方オプションにする- オプションチェーン (
?.
) を使用して、プロパティが存在する場合にのみアクセスする - より柔軟な構造を表現できる
型ガード
interface EmailContact {
email: string;
}
interface PhoneContact {
phone: string;
}
type ContactInfo = EmailContact | PhoneContact;
function isEmailContact(contact: ContactInfo): contact is EmailContact {
return 'email' in contact;
}
function isPhoneContact(contact: ContactInfo): contact is PhoneContact {
return 'phone' in contact;
}
- 特徴
isEmailContact
やisPhoneContact
のような型ガード関数を作成- 型ガード関数を使用して、変数の型を絞り込む
- より安全なコードを書くことができる
ディスクリミネータープロパティ
interface Contact {
kind: 'email' | 'phone';
email?: string;
phone?: string;
}
- 特徴
kind
プロパティをディスクリミネーターとして利用kind
の値によって、email
またはphone
が必須になる- より明確な型定義が可能
マッピング型
type Required<T> = {
[P in keyof T]: T[P];
};
interface PartialContact {
email?: string;
phone?: string;
}
type RequiredContact = Required<PartialContact>; // emailまたはphoneが必須
- 特徴
Required
ユーティリティ型を使用して、すべてのプロパティを必須にする
どの方法を選ぶべきか?
- 汎用性
マッピング型 - 型の安全性
型ガード - シンプルで直感的な表現
ユニオン型
最適な方法は、具体的なユースケースやコードの構造によって異なります。
TypeScriptでは、インターフェースで2つのプロパティのうち少なくとも1つが必須であるという条件を表現する方法は、ユニオン型以外にも様々な方法が存在します。それぞれの方法には特徴があり、状況に応じて使い分けることが重要です。
- コードの可読性や保守性を考慮して、適切な方法を選択しましょう。
- TypeScriptの型システムは非常に強力で、これらの方法以外にも様々な組み合わせや応用が可能です。
typescript