TypeScript中的枚举和普通对象的区别

TypeScript中的枚举和普通对象的区别_第1张图片

下面定义了一个字符串枚举:

enum DayEnum {
    day = '天',
    week = '周',
    month = '月',
    year = '年'
}

这样看起来,和对象好像没有什么区别,如果我们建立一个对象,也能建立 key 对 value 的映射。

const DayEnum = {
    day: '天',
    week: '周',
    month: '月',
    year: '年'
}

枚举类型不可以被修改,枚举是一个只读类型的对象。除此之外还有数字枚举和反向映射,要注意的是不会为字符串枚举成员生成反向映射。

数字枚举

我们先来通过数字枚举的简单例子,来看下枚举是做什么的:

enum Status {// 这里你的TSLint可能会报一个:枚举声明只能与命名空间或其他枚举声明合并。这样的错误,这个不影响编译,声明合并的问题我们在后面的小节会讲。
  Uploading,
  Success,
  Failed
}
console.log(Status.Uploading); // 0
console.log(Status["Success"]); // 1
console.log(Status.Failed); // 2

我们使用 enum 关键字定义了一个枚举值 Status,它包含三个字段,每个字段间用逗号隔开。我们使用枚举值的元素值时,就像访问对象的属性一样,你可以使用’.‘操作符和’[]'两种形式访问里面的值,这和对象一样。

再来看输出的结果,Status.Uploading 是 0,Status['Success']是 1,Status.Failed 是 2,我们在定义枚举 Status 的时候,并没有指定索引号,是因为这是默认的编号,我们也可以自己指定:

// 修改起始编号
enum Color {
  Red = 2,
  Blue,
  Yellow
}
console.log(Color.Red, Color.Blue, Color.Yellow); // 2 3 4
// 指定任意字段的索引值
enum Status {
  Success = 200,
  NotFound = 404,
  Error = 500
}
console.log(Status.Success, Status.NotFound, Status.Error); // 200 404 500
// 指定部分字段,其他使用默认递增索引
enum Status {
  Ok = 200,
  Created,
  Accepted,
  BadRequest = 400,
  Unauthorized
}
console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401

数字枚举在定义值的时候,可以使用计算值和常量。但是要注意,如果某个字段使用了计算值或常量,那么该字段后面紧接着的字段必须设置初始值,这里不能使用默认的递增值了,来看例子:

const getValue = () => {
  return 0;
};
enum ErrorIndex {
  a = getValue(),
  b, // error 枚举成员必须具有初始化的值
  c
}
enum RightIndex {
  a = getValue(),
  b = 1,
  c
}
const Start = 1;
enum Index {
  a = Start,
  b, // error 枚举成员必须具有初始化的值
  c
}

反向映射

我们定义一个枚举值的时候,可以通过 Enum[‘key’]或者 Enum.key 的形式获取到对应的值 value。TypeScript 还支持反向映射,但是反向映射只支持数字枚举,我们后面要讲的字符串枚举是不支持的。来看下反向映射的例子:

enum Status {
  Success = 200,
  NotFound = 404,
  Error = 500
}
console.log(Status["Success"]); // 200
console.log(Status[200]); // 'Success'
console.log(Status[Status["Success"]]); // 'Success'

TypeScript 中定义的枚举,编译之后其实是对象,我们来看下上面这个例子中的枚举值 Status 编译后的样子:

{
    200: "Success",
    404: "NotFound",
    500: "Error",
    Error: 500,
    NotFound: 404,
    Success: 200
}

可以看到,TypeScript 会把我们定义的枚举值的字段名分别作为对象的属性名和值,把枚举值的字段值分别作为对象的值和属性名,同时添加到对象中。这样我们既可以通过枚举值的字段名得到值,也可以通过枚举值的值得到字段名。

字符串枚举

TypeScript2.4 版本新增了字符串枚举,字符串枚举值要求每个字段的值都必须是字符串字面量,或者是该枚举值中另一个字符串枚举成员,先来看个简单例子:

enum Message {
  Error = "Sorry, error",
  Success = "Hoho, success"
}
console.log(Message.Error); // 'Sorry, error'

再来看我们使用枚举值中其他枚举成员的例子:

enum Message {
  Error = "error message",
  ServerError = Error,
  ClientError = Error
}
console.log(Message.Error); // 'error message'
console.log(Message.ServerError); // 'error message'

注意,这里的其他枚举成员指的是同一个枚举值中的枚举成员,因为字符串枚举不能使用常量或者计算值,所以也不能使用其他枚举值中的成员。

异构枚举

简单来说异构枚举就是枚举值中成员值既有数字类型又有字符串类型,如下:

enum Result {
  Faild = 0,
  Success = "Success"
}

但是这种如果不是真的需要,不建议使用。因为往往我们将一类值整理为一个枚举值的时候,它们的特点是相似的。比如我们在做接口请求时的返回状态码,如果是状态码都是数值,如果是提示信息,都是字符串,所以在使用枚举的时候,往往是可以避免使用异构枚举的,重点是做好类型的整理。

你可能感兴趣的:(typescript,javascript,前端,vue.js,开发语言)