TypeScriptが共用体型を導入して以来、列挙型を宣言する理由があるのだろうかと思います。次の列挙型宣言を検討してください。
enum X { A, B, C }
var x:X = X.A;
同様のユニオン型宣言:
type X: "A" | "B" | "C"
var x:X = "A";
基本的に同じ目的を果たし、組合がより強力で表現力豊かであれば、なぜ列挙型が必要なのでしょうか?
enum
を使用する理由はいくつかあります
enum
を反復処理できます。enum
をflags
として使用できます。 ビットフラグユニオンを使用する大きな利点は、複数の型で値を表す簡潔な方法を提供し、非常に読みやすいことです。 let x: number | string
編集:TypeScript 2.4の時点で、Enumは文字列をサポートするようになりました。
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
列挙型は、概念的にはint
および/またはstring
値に専用の共用体タイプのサブセットとして見ることができ、他の応答で使用しやすくするいくつかの追加機能があります。
しかし、列挙型は完全に安全ではありません。
enum Colors { Red, Green, Blue }
const c: Colors = 100; // No errors!
type Color =
| 0 | 'Red'
| 1 | 'Green'
| 2 | 'Blue';
const c2: Color = 100; // Error: Type '100' is not assignable to type 'Color'
ユニオン型は、異種のデータと構造をサポートし、たとえば次のような多相性を可能にします。
class RGB {
constructor(
readonly r: number,
readonly g: number,
readonly b: number) { }
toHSL() {
return new HSL(0, 0, 0); // Fake formula
}
}
class HSL {
constructor(
readonly h: number,
readonly s: number,
readonly l: number) { }
lighten() {
return new HSL(this.h, this.s, this.l + 10);
}
}
function lightenColor(c: RGB | HSL) {
return (c instanceof RGB ? c.toHSL() : c).lighten();
}
列挙型とユニオン型の間では、シングルトンで列挙型を置き換えることができます。それはより冗長ですが、より多くのオブジェクト指向です:
class Color {
static readonly Red = new Color(1, 'Red', '#FF0000');
static readonly Green = new Color(2, 'Green', '#00FF00');
static readonly Blue = new Color(3, 'Blue', '#0000FF');
static readonly All: ReadonlyArray<Color> = [
Color.Red,
Color.Green,
Color.Blue,
]; // `[...] as readonly` to infer `ReadonlyArray<Color>` in TypeScript 3.4
private constructor(
readonly id: number,
readonly label: string,
readonly hex: string) { }
}
const c = Color.Red;
const colorIds = Color.All.map(x => x.id);
私は、F#を見て、優れたモデリング手法を見る傾向があります。 楽しみと利益のためのF#のF#列挙に関する記事 からの引用は、ここで役立つことがあります。
一般に、
int
(またはstring
)値を関連付ける必要がない限り、列挙型よりも識別されたユニオン型を好む必要があります。