TypeScript(七)枚舉

基礎類型中簡單介紹過枚舉,用于將取值限定在一定范圍內(nèi)或定義一些不具有語義性的常量,使之可以清晰的表達意圖。

數(shù)字枚舉

enum Colors {
  red,
  pink,
  blue
}

編譯結(jié)果:

var Colors
;(function (Colors) {
  Colors[(Colors['red'] = 0)] = 'red'
  Colors[(Colors['pink'] = 1)] = 'pink'
  Colors[(Colors['blue'] = 2)] = 'blue'
})(Colors || (Colors = {}))

枚舉成員的值默認從 0 開始自增,同時也會對枚舉值到枚舉名反向映射。

字符串枚舉

在一個字符串枚舉里,每個成員都必須用字符串字面量,或另外一個字符串枚舉成員進行初始化。不可以使用常量枚舉或計算值。

enum Colors {
  red = 'RED',
  pink = 'PINK',
  blue = red
}
Colors.blue // 'RED'

編譯結(jié)果:

var Colors
;(function (Colors) {
  Colors['red'] = 'RED'
  Colors['pink'] = 'PINK'
  Colors['blue'] = 'RED'
})(Colors || (Colors = {}))

由于字符串枚舉沒有自增行為,所以字符串枚舉可以很好的序列化。 換句話說,數(shù)字枚舉的值通常并不能表達有用的信息(盡管反向映射會有所幫助),但字符串枚舉允許提供一個運行時有意義的并且可讀的值,獨立于枚舉成員的名字。

手動賦值

可以對單個或者全部枚舉成員手動賦值。

當對某個枚舉成員賦值后,該枚舉之后未手動賦值的枚舉項會接著遞增。

enum Colors {
  red,
  pink = 3,
  blue
}
Colors.blue // 4
enum Colors {
  red = 1,
  pink = 3,
  blue = 5
}
Colors.blue // 5

如果未手動賦值的枚舉項與手動賦值的重復了,TypeScript 編譯時不會進行限制:

enum Colors {
  red = 3,
  pink = 1,
  blue,
  black,
  orange
}

Colors.red // 3
Colors.black // 3
Colors[3] // 'black'
Colors[3] // 'black'

以上枚舉遞增到 3 的時候與前面的 red 的取值重復了,但是 TypeScript 并沒有報錯,導致 Colors[3] 的值先是 "red",而后又被 "black" 覆蓋。編譯的結(jié)果是如下,所以使用的時候需要注意,不要出現(xiàn)覆蓋的情況。

var Colors
;(function (Colors) {
  Colors[(Colors['red'] = 3)] = 'red'
  Colors[(Colors['pink'] = 1)] = 'pink'
  Colors[(Colors['blue'] = 2)] = 'blue'
  Colors[(Colors['black'] = 3)] = 'black'
  Colors[(Colors['orange'] = 4)] = 'orange'
})(Colors || (Colors = {}))

此外手動賦值的枚舉項也可以為小數(shù)或負數(shù),之后未手動賦值的項的遞增步長仍為 1:

enum Colors {
  red = 1.5,
  pink,
  blue,
  black = -1,
  orange
}

Colors.pink // 2.5
Colors.orange // 0

常數(shù)項和可計算成員

當給某一個枚舉成員設置常量或計算所得值后,其之后的成員必須手動初始化。

可計算成員的意思就是:初始化枚舉成員時,可使用表達式、函數(shù)等方式動態(tài)求值,還可以是對之前定義的常量枚舉成員的引用。

常數(shù)項

const num = 2

enum Colors {
  pink = 4,
  red = num,
  blue = 7
}

以上將常量 num 賦值給枚舉成員 red,則其之后的成員必須初始化,否則編譯報錯:

const num = 2

enum Colors {
  pink = 4,
  red = num,
  blue
}
// Enum member must have initializer.

計算所得值

function getNum() {
  return 3
}
enum Colors {
  red = 1,
  blue = getNum(),
  pink = 6
}
enum Colors {
  red = 1,
  blue = 'sina'.length,
  pink = 6
}

反向映射

除了創(chuàng)建一個以屬性名做為對象成員的對象之外,數(shù)字枚舉的成員還具有反向映射,從枚舉值到枚舉名。如下:

enum Colors {
  red
}
Colors.red // 0
Colors[0] // 'red'

編譯結(jié)果:

var Colors
;(function (Colors) {
  Colors[(Colors['red'] = 0)] = 'red'
})(Colors || (Colors = {}))

ts 編譯生成的 js 代碼中,數(shù)字枚舉類型被編譯成一個對象,包含正向映射( key -> value)和反向映射( value -> key)。

注意:字符串枚舉的成員不會生成反向映射。

異構(gòu)枚舉

枚舉可以混合字符串和數(shù)字成員(不建議)

enum Colors {
  red = 'RED',
  pink = 'PINK',
  blue = 4
}

運行時枚舉

枚舉在運行時是真正存在的對象,因為 ts 會將枚舉編譯成 js 對象。

enum Colors {
  red
}

function bar(obj, key) {
  return obj[key]
}
bar(Colors, 'red')

編譯結(jié)果:

var Colors
;(function (Colors) {
  Colors[(Colors['red'] = 0)] = 'red'
})(Colors || (Colors = {}))

function bar(obj, key) {
  return obj[key]
}
bar(Colors, 'red')

const(常量)枚舉

常量枚舉通過在枚舉上使用 const 修飾符來定義。

const enum Colors {
  red = 4
}
function bar() {
  return Colors.red
}
bar() // 4

常量枚舉與普通枚舉不一樣它會在編譯階段被刪除。因為普通枚舉會被編譯成 js 對象,可以將常量枚舉理解成在編譯階段首先生成 js 對象,然后將所有的枚舉值計算出來,然后刪除對象。

編譯結(jié)果:

function bar() {
  return 4 /* red */
}
bar()

所以在運行時不可以使用常量枚舉。比如:

const enum Colors {
  red
}
console.log(Colors)
// 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query.
//  ("const" 枚舉僅可在屬性、索引訪問表達式、導入聲明的右側(cè)、導出分配或類型查詢中使用。)

聯(lián)合枚舉與枚舉成員的類型

首先解釋字面量枚舉成員。

字面量枚舉成員是指不帶有初始值的常量枚舉成員,或者是值被初始化為以下三種情況的枚舉成員。

  • 任何字符串字面量;
  • 任何數(shù)字字面量
  • 應用了一元 - 符號的數(shù)字字面量
  1. 不帶有初始值的常量枚舉成員
enum Colors {
  red
}
  1. 任何字符串字面量:
enum Colors {
  red = 'RED'
}
  1. 任何數(shù)字字面量:
enum Colors {
  red = 1
}
  1. 應用了一元 - 符號的數(shù)字字面量:
enum Colors {
  red = -10
}

當所有枚舉成員都擁有字面量枚舉值時,枚舉成員或枚舉可以當作類型使用。

枚舉成員類型

枚舉成員類型是指將枚舉的某些成員當作類型使用。

enum Colors {
  red = 'RED'
  pink = 'PINK'
}
interface Tomato {
  color: Colors.red
}
const tomato: Tomato = {
  color: Colors.red
  // color: Colors.pink
  // Type 'Colors.pink' is not assignable to type 'Colors.red'.
}

枚舉類型

枚舉類型本身變成了每個枚舉成員的聯(lián)合類型。

enum Colors {
  red = 'RED',
  pink = 'PINK'
}
interface IColor {
  color: Colors
}

const tomato: IColor = {
  color: Colors.red
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容