给团队做次TypeScript分享(二)—— 枚举

265 阅读3分钟

枚举

说到枚举类型时,我们先了解下什么是枚举

使用枚举可以定义一批有名字的常量,枚举值是数值或字符串

定义

  • 数字枚举

      enum countEnum {
        apple = 18,
        banner = 29,
        pear = 80,
      }
      console.log(countEnum.apple); // 18
      console.log(countEnum.banner); // 29
      console.log(countEnum.pear); // 80
    
  • 字符串枚举

    enum colorEnum {
    	red = 'red',
        blue = 'blue',
        yellow = 'yellow'
    }
    console.log(colorEnum.red); // red
    console.log(colorEnum.blue); // blue
    console.log(colorEnum.yellow); // yellow
    

如果枚举没有赋值,则枚举会从 0 开始,依次自增赋值,也就是说

enum quantity {
    zero,
    one,
    two,
    three,
}
console.log(quantity.zero); // 0
console.log(quantity.one); // 1
console.log(quantity.two); // 2
console.log(quantity.three); // 3

也可以定义某些初始化值,让其他自增,比如

  enum quantity {
    zero = 2021,
    one,
    two,
    three,
  }
  console.log(quantity.zero); // 2021
  console.log(quantity.one); // 2022
  console.log(quantity.two); // 2023
  console.log(quantity.three); // 2024

也可以从中间定义初始值

  enum quantity {
    zero,
    one,
    two = 2021,
    three,
  }
  console.log(quantity.zero); // 0
  console.log(quantity.one); // 1
  console.log(quantity.two); // 2021
  console.log(quantity.three); // 2022

但是不能初始值不能为字符串

  enum quantity {
    zero,
    one = '科技',
    two,
    three,
  }
  // error 报错

但是如果是最后一位就可以,但是枚举中一般不建议混合使用字符串和数字。

  enum quantity {
    zero,
    one,
    two,
    three = '科技',
  }
  console.log(quantity.zero); // 0
  console.log(quantity.one); // 1
  console.log(quantity.two); // 2
  console.log(quantity.three); // 科技

枚举成员的值

可以是常量或是计算表达式,也可以是另外的枚举成员,例如:

  enum color {
    red = "red",
    blue = "blue",
  }

  enum example {
    a,
    b = 1 << 1,
    c = color.red,
    d = "123".length + "321".length,
    e = a || d,
    f = "天天" + "向上",
  }

  console.log(example.a); // 0
  console.log(example.b); // 2
  console.log(example.c); // red
  console.log(example.d); // 6
  console.log(example.e); // 6
  console.log(example.f); // 天天向上

枚举作为类型

enum类型是对JavaScript标准数据类型的一个补充

枚举成员作为类型

只有枚举的所有成员都是字面量枚举成员才可以作为类型

字面量枚举成员包括

  • 不带初始值的常量枚举
  • 任何字符串字面量
  • 任何数字字面量
  • 应用了一元 -符号的数字字面量,比如(-1)
enum notLiteralEnum {
  a,
  b = 1 << 1,
}
let variable:notLiteralEnum.a // error 枚举类型“notLiteralEnum”包含非字面量枚举
  
enum TaxEnum {
  vat = "10101",
  consumption = "10102",
  corporateIncome = "10104",
  personalIncome = "10106",
}
let tax1:TaxEnum.vat = TaxEnum.vat // ok
let tax2:TaxEnum.vat = "10101" // 注意:这样是会报错的

enum otherTax {
  vat = "10101",
  consumption = "10102",
  corporateIncome = "10104",
  personalIncome = "10106",
}
let tax3:TaxEnum.vat = otherTax.vat // 这样也是会报错的,不同枚举类型之间是不兼容的。

枚举本身作为类型

枚举本身可以作为所有成员的联合类型,例如

enum TaxEnum {
  vat = "10101",
  consumption = "10102",
  corporateIncome = "10104",
  personalIncome = "10106",
}

let tax: TaxEnum = TaxEnum.vat;
// 这里的 TaxEnum 类型相当于 TaxEnum.vat | TaxEnum.consumption | TaxEnum.corporateIncome | TaxEnum.personalIncome

数字枚举的缺陷

enum weekday {
  monday =  1,
  tuesday =  2,
  wednesday =  3,
  thursday =  4,
  friday =  5,
}

let today: weekday = 2022 // 竟然是 ok 的

将数字枚举作为类型使用时,允许的值不仅是枚举成员的值,而是可以接受任何数字。

建议尽可能使用字符串枚举,可读性更高,类型检查也更严格

反向映射

即可以通过枚举值获取枚举名字

  enum quantity {
    zero = 2021,
    one,
    two,
    three,
  }

  let zero = quantity.zero;
  console.log(quantity[zero]); // zero
  console.log(quantity[2022]); // one

但是,只有数字枚举成员可以反向映射,字符串不行

enum TaxEnum {
  vat = "10101",
  consumption = "10102",
  corporateIncome = "10104",
  personalIncome = "10106",
}

let vat = TaxEnum.vat;
console.log(TaxEnum[vat]); // undefined