打字稿有工会,枚举是多余的?

Typescript has unions, so are enums redundant?

自从typescript引入联合类型以来,我想知道是否有任何理由声明枚举类型。考虑以下枚举类型声明:

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

以及类似的联合类型声明:

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

如果它们基本上服务于相同的目的,并且联合更强大和更具表现力,那么为什么需要枚举呢?


据我所见,它们并不是多余的,原因很简单,因为联合类型纯粹是一个编译时概念,而枚举实际上是在生成的javascript(示例)中产生并结束的。

这允许您对枚举执行某些操作,而这些操作在联合类型中是不可能的(例如枚举可能的枚举值)。


您可能希望使用enum的原因有很多

  • 您可以迭代一个enum
  • 您可以使用enum作为flags。位标志
  • 下面是一些用例。Enums字体深跳水。

我看到使用联合的最大优点是它们提供了一种简洁的方法来用多种类型表示一个值,而且它们非常可读。let x: number | string

编辑:从typescript 2.4开始,枚举现在支持字符串。

1
2
3
4
5
enum Colors {
  Red ="RED",
  Green ="GREEN",
  Blue ="BLUE",
}


从概念上讲,枚举可以看作是联合类型的一个子集,专用于int和/或string值,其他响应中提到的一些附加特性使其易于使用。

但Enum并不完全安全:

1
2
3
4
5
6
7
8
9
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'

联合类型支持异构数据和结构,例如启用多态性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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();
}

在枚举和联合类型之间,单例可以替换枚举。它更详细,但也更面向对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 Enums的文章中关于f Enums的趣味性和利润的话,这在这里很有用:

In general, you should prefer discriminated union types over enums, unless you really need to have an int (or a string) value associated with them