TypeScript程式語言的列舉,是TypeScript特有、JavaScript沒有的東西。列舉可以快速地將多個不同的值加上名稱並群組化。



直接舉個例子來說明TypeScript列舉的用法:

enum Level {
    One,
    Two,
    Three
}

console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);

以上程式的輸出結果如下:

0
1
2

預設的列舉,可以直接定義出數個名稱,稱為變體(Variant),每個變體所代表的值即為它們的序數(ordinal),從0開始數。

如果我們要改變變體所代表的數值,可以在變體後面使用=來指派數值。一旦有變體的值是明確指派某個數值的話,這個變體後面的其它變體的值就會預設是這個變體的值加NN為這個變體與其它變體的序數差。

列舉的變體可以透過在列舉名稱後加上句點.的方式來讀取,但它的值無法被改變。

例如:

enum Level {
    One,
    Two = 10,
    Three ,
    Four,
    Five = 20.5,
    Six
}

console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);
console.log(Level.Four);
console.log(Level.Five);
console.log(Level.Six);

以上程式的輸出結果如下:

0
10
11
12
20.5
21.5

如果指派給變體的值不是數值的話,則這個變體之後的值必須要手動指派,不然會編譯錯誤。

例如:

enum Level {
    One,
    Two = 10,
    Three,
    Four,
    Five = 20.5,
    Six,
    Seven = "25",
    Eight = 30,
    Night
}

console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);
console.log(Level.Four);
console.log(Level.Five);
console.log(Level.Six);
console.log(Level.Seven);
console.log(Level.Eight);
console.log(Level.Night);

以上程式中的Eight變體必須要手動指派值,因為Seven變體的值不是數值。

列舉也是一個型別,例如:

enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

function isWeekend(day: Weekday) {
    switch (day) {
        case Weekday.Saturday:
        case Weekday.Sunday:
            return true;
        default:
            return false;
    }
}

console.log(isWeekend(Weekday.Monday));
console.log(isWeekend(Weekday.Saturday));

isWeekend函數有一個型別為Weekdayday參數,如果day參數的值是Weekday.Saturday或是Weekday.Sunday的話,就回傳true,否則回傳false

以上程式會輸出:

false
true

如果列舉的變體的值是數值的話,我們可以直接利用數值來表示該變體。例如以上程式可以修改如下:

enum Weekday {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}

function isWeekend(day: Weekday) {
    return day === 6 || day === 7;
}

console.log(isWeekend(1));
console.log(isWeekend(6));

定數型別

定數也可以直接當作型別來用,常拿來代替列舉。

例如:

function isWeekend(day: 1|2|3|4|5|6|7) {
    return day === 6 || day === 7;
}

console.log(isWeekend(1));
console.log(isWeekend(6));

以上程式,isWeekend函數的day,只能傳入數值1~7。

再舉一個例子:

let o: { a: 1, b: 2 } = {a: 1, b: 2};
let a: [1, 2] = [1, 2];
let f: (n: 1) => 2 = (n) => 2;

以上程式,限定了o物件只能是{ a: 1, b: 2 }a陣列只能是[1, 2]f函數只能是(n: 1) => 2

再來一個例子:

let o: { a: 1 | 2, b: number | string } = {a: 1, b: 2};

以上程式,限定了o物件的a屬性的值只能是1或是2b屬性的值只可以是數值或是字串型別。

TypeScript在推論const宣告出來的常數型別時,如果常數值是基本資料型別,則其型別會被推論為定數型別(即直接將值當作型別),表示其無法被更改!

舉例來說:

const a = 1;
const b = "Hello!";

以上a常數的型別為1b常數的型別為"Hello!"

常數列舉

我們再來看這個例子:

enum Level {
    One,
    Two,
    Three
}

console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);

以上程式在經過TypeScript編譯之後,得到的JavaScript程式碼如下:

var Level;
(function (Level) {
    Level[Level["One"] = 0] = "One";
    Level[Level["Two"] = 1] = "Two";
    Level[Level["Three"] = 2] = "Three";
})(Level || (Level = {}));
console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);

如果我們確定這個列舉只會在這個程式專案下用到的話,可以在enum關鍵字前面加上const關鍵字,使其成為常數列舉。

例如:

const enum Level {
    One,
    Two,
    Three
}

console.log(Level.One);
console.log(Level.Two);
console.log(Level.Three);

以上程式會被編譯為:

console.log(0);
console.log(1);
console.log(2);

看到以上的JavaScript程式就可以知道,我們應該要儘量使用常數列舉,讓JavaScript程式在執行階段不會有額外的開支(overhead)。

總結

在這個章節中我們學會了TypeScript提供的列舉用法,以及定數型別的用法。在下一個章節要來學習TypeScript提供的泛型(generic)用法。

下一章:TypeScript程式語言的泛型