TypeScript 类

TypeScript 向 JavaScript 类添加类型和可见性修饰符。

学习更多 JavaScript 类,请访问 这里


成员类型

类(属性和方法)的成员使用类型声明进行类型设置,类似于变量。

实例
  1. class Person {
  2. name: string;
  3. }
  4. const person = new Person();
  5. person.name = "Jane";
  6. console.log(person);

成员可见性

类成员也会被赋予影响可见性的特殊修饰符。

TypeScript 中有 3 种主要的可见性修饰符:

  • public -(默认值)允许从任何地方访问类成员
  • private - 仅允许从类内访问类成员
  • protected - 允许从类成员本身以及继承它的任何类访问该类成员,这将在下面的继承部分中介绍
实例
  1. class Person {
  2. private name: string;
  3. public constructor(name: string) {
  4. this.name = name;
  5. }
  6. public getName(): string {
  7. return this.name;
  8. }
  9. }
  10. const person = new Person("Jane");
  11. console.log(person.getName()); // person.name 无法从类的外部访问,因为它是 private 私有的。

类中的 this 关键字通常指该类的实例。阅读更多关于 this 方面的信息。


参数属性

TypeScript 通过向参数添加可见性修饰符,提供了一种在构造函数中定义类成员的便捷方法。

实例
  1. class Person {
  2. // name 是一个私有成员变量
  3. public constructor(private name: string) {}
  4. public getName(): string {
  5. return this.name;
  6. }
  7. }
  8. const person = new Person("Jane");
  9. console.log(person.getName());

只读

与数组类似,readonly 关键字可以防止更改类成员。

  1. class Person {
  2. private readonly name: string;
  3. public constructor(name: string) {
  4. // name 不能在初始定义之后更改,初始定义必须在其声明或构造函数中。
  5. this.name = name;
  6. }
  7. public getName(): string {
  8. return this.name;
  9. }
  10. }
  11. const person = new Person("Jane");
  12. console.log(person.getName());

继承: 实现

接口(此处介绍)可用于定义类在 implements 关键字中必须遵循的类型。

  1. interface Shape {
  2. getArea: () => number;
  3. }
  4. class Rectangle implements Shape {
  5. public constructor(protected readonly width: number, protected readonly height: number) {}
  6. public getArea(): number {
  7. return this.width * this.height;
  8. }
  9. }
  10. const myRect = new Rectangle(10,20);
  11. console.log(myRect.getArea());

一个类可以通过在 implements 之后列出每个接口来实现多个接口,每个接口之间用逗号分隔,比如:class Rectangle implements Shape, Colored {


继承: 扩展

类可以通过 extends 关键字相互扩展。一个类只能扩展另一个类。

  1. interface Shape {
  2. getArea: () => number;
  3. }
  4. class Rectangle implements Shape {
  5. public constructor(protected readonly width: number, protected readonly height: number) {}
  6. public getArea(): number {
  7. return this.width * this.height;
  8. }
  9. }
  10. class Square extends Rectangle {
  11. public constructor(width: number) {
  12. super(width, width);
  13. }
  14. // getArea 从 Rectangle 中继承
  15. }
  16. const mySq = new Square(20);
  17. console.log(mySq.getArea());

重写

当一个类扩展另一个类时,它可以用相同的名称替换父类的成员。

较新版本的 TypeScript 可以使用 override 关键字进行显式标记。

  1. interface Shape {
  2. getArea: () => number;
  3. }
  4. class Rectangle implements Shape {
  5. // 为这些成员使用 protected 可以访问从该类扩展而来的类,例如 Square
  6. public constructor(protected readonly width: number, protected readonly height: number) {}
  7. public getArea(): number {
  8. return this.width * this.height;
  9. }
  10. public toString(): string {
  11. return `Rectangle[width=${this.width}, height=${this.height}]`;
  12. }
  13. }
  14. class Square extends Rectangle {
  15. public constructor(width: number) {
  16. super(width, width);
  17. }
  18. // 此toString 替换 Rectangle 中的 toString
  19. public override toString(): string {
  20. return `Square[width=${this.width}]`;
  21. }
  22. }
  23. const mySq = new Square(20);
  24. console.log(mySq.toString());
默认情况下,重写方法时,override 关键字是可选的,仅有助于防止意外重写不存在的方法。使用 NoImplicitoOverride 设置强制在重写时使用。

抽象类

抽象类的编写方式可以使它们用作其他类的基类,而不必实现所有成员。这是通过使用 abstract 关键字来实现的。未实现的成员也使用 abstract 关键字。

  1. abstract class Polygon {
  2. public abstract getArea(): number;
  3. public toString(): string {
  4. return `Polygon[area=${this.getArea()}]`;
  5. }
  6. }
  7. class Rectangle extends Polygon {
  8. public constructor(protected readonly width: number, protected readonly height: number) {
  9. super();
  10. }
  11. public getArea(): number {
  12. return this.width * this.height;
  13. }
  14. }
  15. const myRect = new Rectangle(10,20);
  16. console.log(myRect.getArea());
抽象类不能直接实例化,因为它们没有实现所有成员。