web-dev-qa-db-ja.com

タイプスクリプトには共用体があるため、列挙型は冗長ですか?

TypeScriptが共用体型を導入して以来、列挙型を宣言する理由があるのだろうかと思います。次の列挙型宣言を検討してください。

enum X { A, B, C }
var x:X = X.A;

同様のユニオン型宣言:

type X: "A" | "B" | "C"
var x:X = "A";

基本的に同じ目的を果たし、組合がより強力で表現力豊かであれば、なぜ列挙型が必要なのでしょうか?

33
prmph

私が見る限り、それらは冗長ではありません。ユニオン型は純粋にコンパイル時の概念であるのに対し、列挙型は実際にコンパイルされ、結果のjavascriptになります( sample )。

これにより、enumを使用していくつかのことを行うことができます。それ以外の場合は、ユニオン型では不可能です( 可能な列挙値の推定

23
Amid

enumを使用する理由はいくつかあります

ユニオンを使用する大きな利点は、複数の型で値を表す簡潔な方法を提供し、非常に読みやすいことです。 let x: number | string

編集:TypeScript 2.4の時点で、Enumは文字列をサポートするようになりました。

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
} 
15
matthew

列挙型は、概念的には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値を関連付ける必要がない限り、列挙型よりも識別されたユニオン型を好む必要があります。

3
Romain Deneau