TypeScriptでサブセット型を作成する2つの方法:型エイリアスとジェネリック型
TypeScriptにおけるサブセット型
サブセット型の利点
サブセット型を使用する利点は次のとおりです。
- 柔軟性の向上: 基底型を拡張することで、新しい機能を追加することができます。
- コードの可読性向上: 型注釈により、コードの意味を理解しやすくなります。
- 型安全性向上: プログラムの意図を明確にし、型エラーを防ぐことができます。
サブセット型の作成方法
TypeScriptでサブセット型を作成するには、以下の2つの方法があります。
インターフェース拡張
インターフェース拡張は、既存のインターフェースを継承し、新しいプロパティを追加する最も一般的な方法です。
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
department: string;
}
この例では、Employee
インターフェースはPerson
インターフェースを継承し、employeeId
とdepartment
という2つの新しいプロパティを追加しています。
型エイリアス
型エイリアスを使用して、既存の型のサブセット型を作成することもできます。
type Employee = Person & {
employeeId: number;
department: string;
}
この例では、Employee
型エイリアスはPerson
型と{ employeeId: number, department: string }
型の交差型として定義されています。これは、Employee
型の値はPerson
型のすべてのプロパティを持ち、さらにemployeeId
とdepartment
という2つのプロパティを持つことを意味します。
サブセット型を使用する際には、以下の点に注意する必要があります。
- 互換性: サブセット型は、基底型よりも互換性が低くなります。つまり、サブセット型の値は、基底型を期待するすべての場所でで使用できるわけではありません。
- 追加プロパティの型: 追加するプロパティの型は、基底型のプロパティの型と互換性がある必要があります。
例1:インターフェース拡張を使ったサブセット型
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
department: string;
}
function printEmployeeInfo(employee: Employee) {
console.log(`Employee name: ${employee.name}`);
console.log(`Employee age: ${employee.age}`);
console.log(`Employee ID: ${employee.employeeId}`);
console.log(`Employee department: ${employee.department}`);
}
const employee: Employee = {
name: "John Doe",
age: 30,
employeeId: 12345,
department: "Engineering"
};
printEmployeeInfo(employee);
このコードを実行すると、次の出力がコンソールに出力されます。
Employee name: John Doe
Employee age: 30
Employee ID: 12345
Employee department: Engineering
例2:型エイリアスを使ったサブセット型
この例では、型エイリアスを使用して、Person
型のサブセット型であるEmployee
型を作成します。
type Person = {
name: string;
age: number;
};
type Employee = Person & {
employeeId: number;
department: string;
};
function printEmployeeInfo(employee: Employee) {
console.log(`Employee name: ${employee.name}`);
console.log(`Employee age: ${employee.age}`);
console.log(`Employee ID: ${employee.employeeId}`);
console.log(`Employee department: ${employee.department}`);
}
const employee: Employee = {
name: "Jane Doe",
age: 25,
employeeId: 54321,
department: "Sales"
};
printEmployeeInfo(employee);
このコードは、例1とほぼ同じ出力をコンソールに出力します。
ジェネリック型
ジェネリック型を使用して、基底型と追加プロパティの型をパラメーターとして渡すことができます。
interface BaseInterface<T> {
name: string;
age: number;
}
interface Employee extends BaseInterface<Employee> {
employeeId: number;
department: string;
}
function printInfo<T extends BaseInterface<T>>(person: T) {
console.log(`Name: ${person.name}`);
console.log(`Age: ${person.age}`);
if ('employeeId' in person) {
console.log(`Employee ID: ${person.employeeId}`);
console.log(`Department: ${person.department}`);
}
}
const employee: Employee = {
name: "John Doe",
age: 30,
employeeId: 12345,
department: "Engineering"
};
printInfo(employee);
const customer: BaseInterface<Customer> = {
name: "Jane Doe",
age: 25
};
printInfo(customer);
この例では、BaseInterface
というジェネリック型を定義し、name
とage
という2つのプロパティを持つオブジェクトを表します。Employee
インターフェースは、BaseInterface
を拡張し、employeeId
とdepartment
という2つのプロパティを追加します。
printInfo
関数は、ジェネリック型T
を引数として受け取り、T
がBaseInterface
を拡張していることを前提として、name
とage
プロパティにアクセスします。さらに、employeeId
プロパティが存在するかどうかを確認し、存在する場合はdepartment
プロパティにもアクセスします。
Name: John Doe
Age: 30
Employee ID: 12345
Department: Engineering
Name: Jane Doe
Age: 25
型パラメーターを使用した制約
型パラメーターを使用して、サブセット型の制約を定義することができます。
interface Person {
name: string;
age: number;
}
function makeEmployee<T extends Person>(person: T, additionalProps: { employeeId: number; department: string }): Employee & T {
return {
...person,
...additionalProps
};
}
const employee = makeEmployee({ name: "John Doe", age: 30 }, { employeeId: 12345, department: "Engineering" });
console.log(employee.name); // John Doe
console.log(employee.age); // 30
console.log(employee.employeeId); // 12345
console.log(employee.department); // Engineering
この例では、makeEmployee
関数を定義し、person
とadditionalProps
という2つの引数を受け取ります。person
引数はPerson
型の値である必要があり、additionalProps
引数はemployeeId
とdepartment
という2つのプロパティを持つオブジェクトである必要があります。
makeEmployee
関数は、person
とadditionalProps
のスプレッド構文を使用して、新しいオブジェクトを作成します。この新しいオブジェクトは、Person
型のすべてのプロパティと、additionalProps
オブジェクトのすべてのプロパティを持ちます。
John Doe
30
12345
Engineering
共用型
共有型を使用して、複数のサブセット型で共通するプロパティを定義することができます。
interface Address {
street: string;
city: string;
state: string;
postalCode: string;
}
interface Person {
name: string;
age: number;
address: Address;
}
interface Employee extends Person {
employeeId: number;
department: string;
}
interface Customer extends Person {
customerId: number;
membershipLevel: string;
}
function printInfo(person: Person & (Employee | Customer)) {
console.log(`Name: ${person.name}`);
console.log(`Age: ${person.age}`);
console.log(`Address: ${person.address.street}, ${person.address.city}, ${person.address.state} ${person.address.postalCode}`);
if ('
interface typescript