TypeScript | 青训营笔记

41 阅读3分钟

TypeScript 是 JavaScript 的一种超集,它允许我们使用静态类型来编写 JavaScript 代码,从而提高代码的可靠性和可维护性。它添加了很多有用的特性,例如类、模块、接口、类型注解等,并且可以让我们利用现代化的 ECMAScript 特性,例如箭头函数、类的成员变量初始化、可选属性等。

TypeScript 的主要优点包括:

  1. 静态类型检查:通过类型检查能够更早地发现代码中的错误,减少调试时间,提高代码质量。

  2. 提高可读性和可维护性:静态类型可以增强代码的可读性和可维护性,代码易于理解,易于维护。

  3. 完善的 IDE 支持:现在很多主流的编辑器和IDE都支持 TypeScript,例如Visual Studio Code、WebStorm、Sublime Text等,它们能够提供代码自动补全、语法检查、重构等强大的功能。

  4. 简化代码编写:TypeScript 提供了接口、枚举、泛型等高级特性,简化了代码编写和维护。

下面我们来看一些 TypeScript 的具体用法。

数据类型

TypeScript 的数据类型与 JavaScript 类似,但增加了类型注解的特性。在 TypeScript 中我们可以指定变量或函数的参数、返回值等的类型,从而确保代码的正确性。

布尔类型

boolean 类型表示逻辑值,只有两个值,true 和 false。

let isDone: boolean = false;

数字类型

number 类型表示数字,包括整数和小数。

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

字符串类型

string 类型表示字符串,它可以是单引号(')、双引号(")或反引号(`)括起来的一串字符。

let name: string = 'Tom';
let age: number = 18;
let introduction: string = `My name is ${name}, and I'm ${age} years old.`

数组

在 TypeScript 中,可以使用两种方式来定义数组类型。

// 方式一:元素类型 followed by []
let list: number[] = [1, 2, 3];

// 方式二:Array<元素类型>
let list: Array<number> = [1, 2, 3];

元组

元组表示一个已知元素数量和类型的数组,各元素的类型不必相同。元组类型的变量可以使用数组的下标方式访问,也可以使用元素名称方式访问。

let tuple: [string, number] = ['Tom', 18];
let name: string = tuple[0];
let age: number = tuple[1];

枚举

枚举是一种特殊的数据类型,用于表示一组值中的固定数据,通常用于状态码定义、选项定义、状态传递等场景。

enum Color {Red, Green, Blue}
let c: Color = Color.Green;

Any

any 类型表示任意类型,这种类型的变量可以存储任意类型的值。在使用 any 类型时应当慎用,因为这样会使代码变得不可读,也会失去 TypeScript 的类型检查优势。

let anyType: any = 1;
anyType = 'Tom';
anyType = true;

Void

void 类型表示空类型,一般用于函数返回值的类型声明。当一个函数没有返回值时,它的返回类型就是 void。

function sayHello(name: string): void {
    console.log(`Hello, ${name}!`)
}
sayHello('Tom');

Null 和 Undefined

在 JavaScript 中,null 和 undefined 代表“没有值”,在 TypeScript 中,这两个类型也被称为 null 类型和 undefined 类型。

let u: undefined = undefined;
let n: null = null;

Never

never 类型表示那些永远不会发生的值。例如,一个函数的返回类型为 never ,那么它要么会抛出一个异常,要么永远不会返回。

function error(message: string): never {
    throw new Error(message);
}
function infiniteLoop(): never {
    while (true) {}
}

Object

object 类型表示非原始类型,即除 number、string、boolean、symbol、null 或 undefined 之外的类型。因此,一个对象变量如果被定义为 object 类型,那么它可以存储任意非基本数据类型的值。

let obj: object = {};
obj = function() {};
obj = [];

TypeScript 是一个面向对象编程语言,它支持类、继承、封装、抽象类、接口等面向对象特性。

类定义

TypeScript 中使用 class 关键字来定义类。

class Person {
    private name: string;  // 私有成员变量
    constructor(name: string) {  // 构造函数
        this.name = name;
    }
    public sayHello() {  // 公有方法
        console.log(`Hello, ${this.name}!`);
    }
}

对象实例化

类定义后,可以使用 new 关键字来创建类实例。

let tom: Person = new Person('Tom');
tom.sayHello();

访问控制

可以使用 public、private 或 protected 关键字来明确变量和方法的访问控制,这些关键字用来控制类成员的可见性。其中,在 TypeScript 中,默认情况下,类成员都是 public 的。

class Person {
    private name: string;  // 私有成员变量
    constructor(name: string) {  // 构造函数
        this.name = name;
    }
    public sayHello() {  // 公有方法
        console.log(`Hello, ${this.name}!`);
    }
    private getAge() {  // 私有方法
        return 18;
    }
}

继承

继承是面向对象编程中的一个重要概念,它允许我们创建一个新的类,来扩展已有类的功能。在 TypeScript 中,我们可以使用 extends 关键字来实现类之间的继承关系。

class Animal {
  public name: string;
  constructor(name: string) {
      this.name = name;
  }
  public move(distanceInMeters: number = 0) {
      console.log(`${this.name} moved ${distanceInMeters}m.`);
  }
}

class Snake extends Animal {
  constructor(name: string) {
      super(name);
  }
  public move(distanceInMeters = 5) {
      console.log("Slithering...");
      super.move(distanceInMeters);
  }
}

class Horse extends Animal {
  constructor(name: string) {
      super(name);
  }
  public move(distanceInMeters = 45) {
      console.log("Galloping...");
      super.move(distanceInMeters);
  }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

抽象类

抽象类是一种不能被实例化的类,它只能被继承,用于定义一些基础功能或行为规范。在 TypeScript 中,我们可以使用 abstract 关键字来声明抽象类。

abstract class Department {
    constructor(public name: string) { }
    public printName(): void {
        console.log(`Department name: ${this.name}`);
    }
    abstract printMeeting(): void;
}

class AccountingDepartment extends Department {
    constructor() {
        super("Accounting and Auditing"); // constructors in derived classes must call super()
    }
    printMeeting(): void {
        console.log("The Accounting Department meets each Monday at 10am.");
    }  
}