TypeScript类型定义-进阶篇2

简介: TypeScript类型定义-进阶篇

四、枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等
1、简单的例子

枚举使用 enum 关键字来定义:

    enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

    枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

    enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
    console.log(Days["Sun"] === 0); // true
    console.log(Days["Mon"] === 1); // true
    console.log(Days["Tue"] === 2); // true
    console.log(Days["Sat"] === 6); // true
    console.log(Days[0] === "Sun"); // true
    console.log(Days[1] === "Mon"); // true
    console.log(Days[2] === "Tue"); // true
    console.log(Days[6] === "Sat"); // true

    2、手动赋值

    我们也可以给枚举项手动赋值:

    enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
    console.log(Days["Sun"] === 7); // true
    console.log(Days["Mon"] === 1); // true
    console.log(Days["Tue"] === 2); // true
    console.log(Days["Sat"] === 6); // true

    上面的例子中,未手动赋值的枚举项会接着上一个枚举项递增。

    如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 是不会察觉到这一点的:

    enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};
    console.log(Days["Sun"] === 3); // true
    console.log(Days["Wed"] === 3); // true
    console.log(Days[3] === "Sun"); // false
    console.log(Days[3] === "Wed"); // true

    所以使用的时候需要注意,最好不要出现这种覆盖的情况。

    手动赋值的枚举项可以不是数字,此时需要使用类型断言来让 tsc 无视类型检查 (编译出的 js 仍然是可用的):

      enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"S"};

      当然,手动赋值的枚举项也可以为小数或负数,此时后续未手动赋值的项的递增步长仍为 1

        enum Days {Sun = 7, Mon = 1.5, Tue, Wed, Thu, Fri, Sat};
        console.log(Days["Sun"] === 7); // true
        console.log(Days["Mon"] === 1.5); // true
        console.log(Days["Tue"] === 2.5); // true
        console.log(Days["Sat"] === 6.5); // true

        3、常数项和计算所得项

        枚举项有两种类型:常数项(constant member)和计算所得项(computed member)。

        前面我们所举的例子都是常数项,一个典型的计算所得项的例子:

          enum Color {Red, Green, Blue = "blue".length};

          上面的例子中,"blue".length 就是一个计算所得项。

          上面的例子不会报错,但是如果紧接在计算所得项后面的是未手动赋值的项,那么它就会因为无法获得初始值而报错

            enum Color {Red = "red".length, Green, Blue};

            4、常数枚举

            常数枚举是使用 const enum 定义的枚举类型:

            const enum Directions {
                Up,
                Down,
                Left,
                Right
            }
            let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

            常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员

            假如包含了计算成员,则会在编译阶段报错:

              const enum Color {Red, Green, Blue = "blue".length};
              // index.ts(1,38): error TS2474: In 'const' enum declarations member initializer must be constant expression.

              5、外部枚举

              外部枚举(Ambient Enums)是使用 declare enum 定义的枚举类型:

              declare enum Directions {
                  Up,
                  Down,
                  Left,
                  Right
              }
              let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

              declare 定义的类型只会用于编译时的检查,编译结果中会被删除。

              五、

              1、类的定义

              Demo

              使用 class 定义类,使用 constructor 定义构造函数。

              通过 new 生成新实例的时候,会自动调用构造函数。

              class Animal {
                  constructor(name) {
                      this.name = name;
                  }
                  sayHi() {
                      return `My name is ${this.name}`;
                  }
              }
              let a = new Animal('Jack');
              console.log(a.sayHi()); // My name is Jack

              2、类的继承

              使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。

                class Cat extends Animal {
                    constructor(name) {
                        super(name); // 调用父类的 constructor(name)
                        console.log(this.name);
                    }
                    sayHi() {
                        return 'Meow, ' + super.sayHi(); // 调用父类的 sayHi()
                    }
                }
                let c = new Cat('Tom'); // Tom
                console.log(c.sayHi()); // Meow, My name is Tom
                

                3、访问修饰符

                public private 和 protected

                ·  public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public

                ·  private 修饰的属性或方法是私有的,不能在声明它的类的外部访问

                ·  protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

                使用 private 修饰的属性或方法,在子类中也是不允许访问的:

                  class Animal {
                      private name;
                      public constructor(name) {
                          this.name = name;
                      }
                  }
                  class Cat extends Animal {
                      constructor(name) {
                          super(name);
                              console.log(this.name);
                          }
                      }
                  }
                  而如果是用 protected 修饰,则允许在子类中访问:
                  class Animal {
                      protected name;
                      public constructor(name) {
                          this.name = name;
                      }
                  }
                  class Cat extends Animal {
                      constructor(name) {
                          super(name); 
                          console.log(this.name);
                      }
                  }

                  4、静态属性和静态方法

                  可以使用 static 定义一个静态属性:

                  class Animal {
                      static num = 42;
                      constructor() {
                          // ...
                      }
                  }
                  console.log(Animal.num); // 42

                  使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:

                    class Animal {
                        static isAnimal(a) {
                            return a instanceof Animal;
                        }
                    }
                    let a = new Animal('Jack');
                    Animal.isAnimal(a); // true
                    a.isAnimal(a); // TypeError: a.isAnimal is not a function

                    5、抽象类和多态

                    1. 抽象类是提供其他类继承的基类(父类)不能直接被实例化
                    2. 抽象方法只能包含在抽象类中,抽象类中可以包含抽象方法和非抽象方法
                    3. 子类继承抽象类,实现抽象方法

                    abstract 用于定义抽象类和其中的抽象方法。什么是抽象类?首先,抽象类是不允许被实例化的:

                      abstract class Animal {
                          public name;
                          public constructor(name) {
                                  this.name = name;
                          }
                          public abstract sayHi();
                      }
                      let a = new Animal('Jack');

                      由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 CatDog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat

                      交流

                      我是老礼,公众号「进军全栈攻城狮」作者 ,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

                      相关文章
                      |
                      10月前
                      |
                      JavaScript 前端开发 安全
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(1)
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(1)
                      |
                      10月前
                      |
                      JavaScript
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(2)
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(2)
                      |
                      10月前
                      |
                      JavaScript API
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(3)
                      带你读《现代TypeScript高级教程》十四、扩展类型定义(3)
                      |
                      11月前
                      |
                      JavaScript 索引
                      TypeScript类型定义-进阶篇1
                      TypeScript类型定义-进阶篇
                      |
                      JavaScript 前端开发 安全
                      《现代Typescript高级教程》扩展类型定义
                      扩展类型定义 在 TypeScript 中,我们可以通过声明文件(.d.ts 文件)来为现有的 JavaScript 库提供类型定义,或者为现有的类型添加额外的属性和方法。这个过程通常被称为“类型声明扩展”。在这篇文章中,我们将详细探讨如何通过声明文件扩展类型定义。
                      119 0
                      |
                      JavaScript
                      TypeScript数组类型定义
                      TypeScript数组类型定义
                      |
                      JavaScript
                      TypeScript里的中括号类型定义法
                      TypeScript里的中括号类型定义法
                      274 0
                      TypeScript里的中括号类型定义法
                      |
                      1月前
                      |
                      前端开发 JavaScript 安全
                      TypeScript在React Hooks中的应用:提升React开发的类型安全与可维护性
                      【7月更文挑战第17天】TypeScript在React Hooks中的应用极大地提升了React应用的类型安全性和可维护性。通过为状态、依赖项和自定义Hooks指定明确的类型,开发者可以编写更加健壮、易于理解和维护的代码。随着React和TypeScript的不断发展,结合两者的优势将成为构建现代Web应用的标准做法。
                      |
                      7天前
                      |
                      JavaScript
                      TypeScript——不能将类型“HTMLElement | null”分配给类型“HTMLElement”
                      TypeScript——不能将类型“HTMLElement | null”分配给类型“HTMLElement”
                      19 4
                      |
                      12天前
                      |
                      JavaScript 编译器
                      typescript 解决变量多类型访问属性报错--工作随记
                      typescript 解决变量多类型访问属性报错--工作随记