インターセクション型 (intersection type)
考え方はユニオン型と相対するものです。ユニオン型がどれかを意味するならインターセクション型はどれもです。言い換えるとオブジェクトの定義を合成させることを指します。
インターセクション型を作るためには合成したいオブジェクト同士を&
で列挙します。
typescript
type TwoDimensionalPoint = {x: number;y: number;};type Z = {z: number;};type ThreeDimensionalPoint = TwoDimensionalPoint & Z;const p: ThreeDimensionalPoint = {x: 0,y: 1,z: 2,};
typescript
type TwoDimensionalPoint = {x: number;y: number;};type Z = {z: number;};type ThreeDimensionalPoint = TwoDimensionalPoint & Z;const p: ThreeDimensionalPoint = {x: 0,y: 1,z: 2,};
xy平面上の点を表すTwoDimensionalPoint
を拡張してxyz平面上の点のThreeDimensionalPoint
に変換しました。
#
プリミティブ型のインターセクション型プリミティブ型のインターセクション型をつくることもできますが、作るとnever
という型ができます。
typescript
type Never = string & number;const n: Never = "2";// Type '"2"' is not assignable to type 'never'.
typescript
type Never = string & number;const n: Never = "2";// Type '"2"' is not assignable to type 'never'.
このnever
型にはいかなる値も代入できません。使い道がまるでないように見えますが意外なところで役に立ちます。今回は説明を省きます。
#
インターセクション型を使いこなすシステムの巨大化に伴い、受け付けたいパラメーターが巨大化したとします。
typescript
type Parameter = {id: string;index?: number;active: boolean;balance: number;photo?: string;age?: number;surname: string;givenName: string;company?: string;email: string;phoneNumber?: string;address?: string;// ...};
typescript
type Parameter = {id: string;index?: number;active: boolean;balance: number;photo?: string;age?: number;surname: string;givenName: string;company?: string;email: string;phoneNumber?: string;address?: string;// ...};
一見してどのプロパティが必須で、どのプロパティが選択可かが非常にわかりづらいです。これをインターセクション型とユーティリティ型のRequired<T>
とPartial<T>
を使いわかりやすく表記できます。ユーティリティ型については解説しているページがありますのでご覧ください。
#
必須とそうでないパラメータのタイプエイリアスに分離するtypescript
type Mandatory = {id: string;active: boolean;balance: number;surname: string;givenName: string;email: string;};type Optional = {index: number;photo: string;age: number;company: string;phoneNumber: string;address: string;};
typescript
type Mandatory = {id: string;active: boolean;balance: number;surname: string;givenName: string;email: string;};type Optional = {index: number;photo: string;age: number;company: string;phoneNumber: string;address: string;};
Required<T>, Partial<T>
をつける#
Mantatory
はRequired<T>
を、Optional
はPartial<T>
をつけます。
typescript
type Mandatory = Required<{id: string;active: boolean;balance: number;surname: string;givenName: string;email: string;}>;type Optional = Partial<{index: number;photo: string;age: number;company: string;phoneNumber: string;address: string;}>;
typescript
type Mandatory = Required<{id: string;active: boolean;balance: number;surname: string;givenName: string;email: string;}>;type Optional = Partial<{index: number;photo: string;age: number;company: string;phoneNumber: string;address: string;}>;
#
インターセクション型で合成するこれで最初に定義したParameter
と同じタイプエイリアスができました。
typescript
type Parameter = Readonly<Mandatory & Optional>;
typescript
type Parameter = Readonly<Mandatory & Optional>;