メインコンテンツへスキップ

列挙型の定義

Flow 列挙型を定義する方法を学びましょう。手早く概要を知りたいですか?クイックスタートガイドをご覧ください。

列挙型宣言はステートメントです。その名前は、値(メンバーにアクセスし、メソッドを呼び出すために使用)と、型(メンバーの型の注釈として使用可能)の両方を定義します。

列挙型のメンバーはすべて同じ型である必要があり、それらのメンバーは、文字列数値真偽値、およびシンボルの4つの型のいずれかになります。

すべての列挙型には、共通のプロパティがいくつかあります。

一貫したメンバーの型

列挙型のメンバーの型は一貫している必要があります。たとえば、1つの列挙型でstringnumberのメンバーを混在させることはできません。それらはすべて文字列、数値、またはブール値である必要があります(symbolベースの列挙型には値を指定しません)。

メンバー名の開始文字

メンバー名は有効な識別子(数字で開始しないなど)である必要があり、小文字のaからzで開始してはなりません。これらの文字で始まる名前は、列挙型のメソッド(例:Status.cast(...))用に予約されています。

これは許可されていません。

1enum Status {2  active, // Error: names can't start with lowercase 'a' through 'z'
3}
2:3-2:8: Enum member names cannot start with lowercase 'a' through 'z'. Instead of using `active`, consider using `Active`, in enum `Status`.

一意のメンバー名

メンバー名は一意である必要があります。これは許可されていません。

1enum Status {2  Active,3  Active, // Error: the name 'Active` was already used above
4}
3:3-3:8: Enum member names need to be unique, but the name `Active` has already been used before in enum `Status`.

リテラルメンバー値

列挙型メンバーの値を指定する場合、計算された値ではなく、リテラル(文字列、数値、またはブール値)である必要があります。これは許可されていません。

1enum Status {2  Active = 1 + 2, // Error: the value must be a literal
3}
2:12-2:12: The enum member initializer for `Active` needs to be a literal (either a boolean, number, or string) in enum `Status`.

一意のメンバー値

メンバーの値は一意である必要があります。これは許可されていません。

1enum Status {2  Active = 1,3  Paused = 1, // Error: the value has already been used above
4}
3:12-3:12: Invalid enum member initializer. Initializers need to be unique, but this one has already been used for a previous member [1] of enum `Status` [2]. [duplicate-enum-init]

宣言時に固定

列挙型は拡張可能ではないため、コードの実行中に新しいメンバーを追加することはできません。実行時、列挙型メンバーの値は変更できず、メンバーを削除することもできません。この点で、それらは凍結されたオブジェクトのように動作します。

文字列列挙型

文字列列挙型がデフォルトです。of句(例:enum Status of number {}enum Status of symbol {}など)を指定せず、値(例:enum Status {Active = 1})も指定しない場合、定義はデフォルトで文字列列挙型になります。

他の型の列挙型(例:数値列挙型)とは異なり、列挙型メンバーの値を指定することも、値を指定せずにデフォルト設定にすることもできます。

列挙型メンバーの値を指定しない場合、それらはメンバーの名前と同じ文字列にデフォルト設定されます。

1enum Status {2  Active,3  Paused,4  Off,5}

次と同じです。

1enum Status {2  Active = 'Active',3  Paused = 'Paused',4  Off = 'Off',5}

すべてのメンバーの値を指定するか、どのメンバーの値も指定しないかのいずれかである必要があります。これは許可されていません。

1enum Status {2  Active = 'active',3  Paused = 'paused',4  Off, // Error: you must specify a value for all members (or none of the members)
5}
4:3-4:5: String enum members need to consistently either all use initializers, or use no initializers, in enum Status.

オプションで、of句を使用できます。

1enum Status of string {2  Active,3  Paused,4  Off,5}

of句がない場合、値に基づいて列挙型の型を推論します。of句を使用すると、誤った値を使用した場合、エラーメッセージが常にその型の列挙型として解釈されるようになります。

数値列挙型

数値列挙型には、値を指定する必要があります。

次のように数値列挙型を指定できます。

1enum Status {2  Active = 1,3  Paused = 2,4  Off = 3,5}

オプションで、of句を使用できます。これは、有効なFlow列挙型の型チェック動作には影響しません。定義サイトとして、すべての列挙型メンバーがnumberであることを保証するだけです。

1enum Status of number {2  Active = 1,3  Paused = 2,4  Off = 3,5}

(他の言語とは異なり)数値列挙型のデフォルト設定は許可されていません。これは、そのような列挙型の途中からメンバーが追加または削除された場合、後続のすべてのメンバーの値が変更されるためです。これは危険な場合があります(例:プッシュセーフティ、シリアル化、ロギング)。ユーザーに明示的に番号を付け直すことを要求することで、ユーザーはそうすることの影響について考えるようになります。

提供される値は、数値リテラルである必要があります。(注:JavaScriptでは負の数のリテラルはありません。それらは数値リテラルに対する単項-演算の適用です。)将来、そうするよう要求があった場合、許可される値を特定の非リテラルを含むように拡張する可能性があります。

真偽値列挙型

真偽値列挙型には値を指定する必要があります。真偽値列挙型は、2つのメンバーのみを持つことができます。

次のように真偽値列挙型を指定できます。

1enum Status {2  Active = true,3  Off = false,4}

オプションで、of句を使用できます。これは、有効なFlow列挙型の型チェック動作には影響しません。定義サイトとして、すべての列挙型メンバーがbooleanであることを保証するだけです。

1enum Status of boolean {2  Active = true,3  Off = false,4}

シンボル列挙型

シンボル列挙型は、値を指定することはできません。各メンバーは、メンバー名に設定されたシンボルの説明を持つ新しいシンボルです。値を省略した場合にデフォルトとなる文字列列挙型と区別するために、シンボル列挙型ではof句を使用する必要があります。

次のようにシンボル列挙型を指定できます。

1enum Status of symbol {2  Active,3  Paused,4  Off,5}

不明なメンバーを持つFlow列挙型

宣言の最後に...を追加することで、列挙型に「不明なメンバー」が含まれていることを指定できます。

1enum Status {2  Active,3  Paused,4  Off,5  ...6}7const status: Status = Status.Active;8
9switch (status) {
10 case Status.Active: break;11 case Status.Paused: break;12 case Status.Off: break;13}
9:9-9:14: Missing `default` case in the check of `status`. `Status` [1] has unknown members (specified using `...`) so checking it requires the use of a `default` case to cover those members. [invalid-exhaustive-check]

これを使用した場合、Flowは、既知のすべての列挙型メンバーがチェックされている場合でも、列挙型を切り替えるときに常にdefaultを必要とします。defaultは、明示的にリストされていない「不明な」メンバーをチェックします。

この機能は、列挙型の値が境界を越え、各側の列挙型宣言に異なるメンバーが含まれている可能性がある場合に役立ちます。たとえば、クライアントとサーバーの両方で使用される列挙型定義の場合、列挙型メンバーが追加され、サーバーによってすぐに認識されますが、新しいメンバーをまだ認識していない古いクライアントに送信される可能性があります。

このユースケースの1つは、GraphQL列挙型のJS出力です。不明なメンバーを持つFlow列挙型は、追加された'%future added value'メンバーの代わりに使用できます。

実行時の列挙型

列挙型は、実行時に値として存在します。Flow列挙型宣言をBabel変換を使用して列挙型ランタイムへの呼び出しに変換します(詳細については、列挙型を有効にするドキュメントをお読みください)。すべての列挙型が列挙型のメソッドの実装を共有できるように、ランタイムを使用します。

列挙型のプロトタイプ(列挙型メソッドを持つ)にはObject.create(null)を使用するため、Object.prototypeのプロパティが列挙型を汚染することはありません。列挙型オブジェクトの独自のプロパティは、列挙型メンバーのみです。メンバーは列挙可能ではありません(そのためには.members()メソッドを使用してください)。列挙型オブジェクト全体が凍結されているため、変更することはできません。

スタイルガイド

列挙型の命名

他の型の命名規則に従い、列挙型名をPascalCaseで定義することをお勧めします。すべて大文字の名前(例:STATUS)は読みにくく、推奨されません。

列挙型には単数形で名前を付けることをお勧めします。例:StatusesではなくStatustruefalseの型がbooleansではなくbooleanであるのと同じです。

名前にEnumを追加しないでください(例:列挙型にStatusEnumという名前を付けないでください)。これは不要です。すべてのクラス名にClassを追加したり、すべての型エイリアスにTypeを追加したりしないのと同じです。

列挙型メンバーの命名

列挙型メンバー名をPascalCaseで定義することをお勧めします。すべて大文字の名前(例:ACTIVE)は読みにくく、推奨されません。さらに、Flowはこれらが定数であることを強制するため、プログラマーにその意図を伝えるために名前を使用する必要はありません。

以下も参照してください:列挙型メンバー名の開始文字に関するルール。

別の型を作成しないでください

クラスのように、Flow列挙型は型と値の両方です。別の型エイリアスを作成する必要はありません。列挙型名を使用できます。

メンバーへのアクセスにはドットアクセスを使用してください

const {Active} = Status;ではなく、Status.Activeを優先してください。これにより、テキスト検索で列挙型の使用箇所を見つけやすくなり、どの列挙型が関与しているかを読者に明確にすることができます。さらに、これは列挙型を含むswitchステートメントに必要です。