TypeScript 第二章

在 TypeScript 的第一章中,我们了解了类型注解、类和接口、函数、基本类型和高级类型等基础知识。在本章中,我们将深入学习类型注解的进阶用法、类的继承和多态、泛型、模块和命名空间等高级特性。

进阶的类型注解

在 TypeScript 的第一章中,我们介绍了类型注解的基本用法。在本节中,我们将介绍类型注解的进阶用法,包括类型别名、交叉类型、联合类型和类型保护等。

类型别名

类型别名可以帮助我们为复杂的类型定义更容易记忆和使用的名称。以下是一个类型别名的示例:

type Person = {
  name: string;
  age: number;
};

function greet(person: Person) {
  console.log(`Hello, ${person.name}!`);
}

在这个示例中,我们使用 type 关键字定义了一个名为 Person 的类型别名,它代表了一个拥有 name 和 age 属性的对象类型。在 greet 函数中,我们使用 Person 类型别名来指定参数 person 的类型。

交叉类型

交叉类型可以帮助我们将多个类型合并为一个类型。以下是一个交叉类型的示例:

type Cat = {
  name: string;
  meow(): void;
};

type Fish = {
  swim(): void;
};

type CatFish = Cat & Fish;

let catFish: CatFish = {
  name: "Tom",
  meow() {
    console.log(`${this.name} says meow`);
  },
  swim() {
    console.log(`${this.name} is swimming`);
  },
};

在这个示例中,我们使用 & 操作符将 Cat 和 Fish 类型合并为一个类型别名 CatFish。然后,我们创建了一个 CatFish 类型的对象 catFish,它包含了 Cat 和 Fish 类型的属性和方法。

联合类型

联合类型可以帮助我们指定一个变量的多种可能类型。以下是一个联合类型的示例:

let value: string | number;

value = "hello";
console.log(value.length);

value = 10;
console.log(value.toFixed(2));

在这个示例中,我们使用 | 操作符指定变量 value 的类型为字符串或数字。当我们将变量赋值为字符串时,我们可以使用字符串的 length 属性;当我们将变量赋值为数字时,我们可以使用数字的 toFixed 方法。

类型保护

当我们使用联合类型时,我们需要使用类型保护来确定变量的具体类型。以下是一个类型保护的示例:

function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

printValue("hello");
printValue(10.123);

在这个示例中,我们使用 typeof 操作符来判断变量 value 的类型。当变量的类型为字符串时,我们可以使用字符串的 toUpperCase 方法;当变量的类型为数字时,我们可以使用数字的 toFixed 方法。

类的继承和多态

类的继承和多态是面向对象编程的核心概念之一,它们可以帮助我们组织代码和实现代码的复用。在 TypeScript 中,类的继承和多态同样可以实现。

类的继承

类的继承可以帮助我们从已有的类中派生出新的类,并扩展它们的功能。以下是一个类的继承的示例:

class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

class Cat extends Animal {
  meow()() {
    console.log(`${this.name} says meow`);
  }
}

let cat = new Cat("Tom");
cat.sayHello();
cat.meow();

在这个示例中,我们定义了一个 Animal 类,它包含了一个名为 name 的属性和一个名为 sayHello 的方法。然后,我们定义了一个 Cat 类,它从 Animal 类中继承了 name 属性和 sayHello 方法,并扩展了一个名为 meow 的方法。最后,我们创建了一个 Cat 类的实例 cat,并调用了它的 sayHello 和 meow 方法。

多态

多态可以帮助我们使用基类的引用来调用派生类的方法。以下是一个多态的示例:

class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

class Cat extends Animal {
  meow() {
    console.log(`${this.name} says meow`);
  }
}

class Dog extends Animal {
  bark() {
    console.log(`${this.name} says woof`);
  }
}

let animals: Animal[] = [new Cat("Tom"), new Dog("Max")];

for (let animal of animals) {
  animal.sayHello();

  if (animal instanceof Cat) {
    animal.meow();
  } else if (animal instanceof Dog) {
    animal.bark();
  }
}

在这个示例中,我们定义了一个 Animal 类和两个派生类 Cat 和 Dog。然后,我们创建了一个 Animal 类型的数组 animals,其中包含了一个 Cat 类型的实例和一个 Dog 类型的实例。最后,我们循环遍历 animals 数组,并使用基类的引用来调用派生类的方法。

泛型

泛型可以帮助我们编写更加通用和灵活的代码。在 TypeScript 中,泛型可以应用于函数、类和接口等场景。

泛型函数

泛型函数可以帮助我们编写可以适用于多种类型的函数。以下是一个泛型函数的示例:

function reverse<T>(items: T[]): T[] {
  return items.reverse();
}

let numbers = [1, 2, 3, 4, 5];
let reversedNumbers = reverse(numbers);
console.log(reversedNumbers);

let strings = ["hello", "world"];
let reversedStrings = reverse(strings);
console.log(reversedStrings);

在这个示例中,我们定义了一个名为 reverse 的泛型函数,它接受一个类型为 T 的数组作为参数,并返回一个类型为 T 的数组。然后,我们分别调用了 reverse 函数,并传递了一个数字类型的数组和一个字符串类型的数组作为参数。

泛型类

泛型类可以帮助我们编写可以适用于多种类型的类。以下是一个泛型类的示例:

class Stack<T> {
  private items: T[] = [];

  push(item: T) {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }
}

let stack = new Stack<number>();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.pop());
console.log(stack.pop());
console.log(stack.pop());

let stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
console.log(stringStack.pop());
console.log(stringStack.pop());

在这个示例中,我们定义了一个名为 Stack 的泛型类,它包含了一个名为 items 的私有属性和两个公共方法 push 和 pop。然后,我们分别创建了一个 Stack 类型的实例和一个 Stack 类型的实例,并分别调用了它们的 push 和 pop 方法。

泛型接口

泛型接口可以帮助我们定义可以适用于多种类型的接口。以下是一个泛型接口的示例:

interface Pair<T, U> {
  first: T;
  }

在这个示例中,我们定义了一个泛型接口 Pair,它有两个类型参数 T 和 U。这个接口有一个属性 first,它的类型是 T。

以上是 TypeScript 的类型系统的一些基础知识。在接下来的学习中,我们将深入了解这些概念,并学习更多高级特性。

你可能感兴趣的:(TypeScript,typescript,javascript,前端)