返回

剥丝抽茧,剖析TypeScript中的接口和泛型

前端

TypeScript中的接口

接口是TypeScript中的一种数据类型,它定义了对象的形状,即对象必须拥有的属性和方法。接口可以用来约束变量、函数和构造函数。

约束变量

接口可以用来约束变量。例如,我们可以定义一个名为Person的接口,它定义了nameage两个属性:

interface Person {
  name: string;
  age: number;
}

然后,我们可以使用这个接口来约束一个变量,例如:

let person: Person = {
  name: "John Doe",
  age: 30
};

这样,变量person只能被赋值为一个具有nameage属性的对象。

约束函数

接口也可以用来约束函数。例如,我们可以定义一个名为greet的函数,它接受一个Person对象作为参数,并返回一个字符串:

function greet(person: Person): string {
  return "Hello, " + person.name + "!";
}

然后,我们可以使用这个函数来约束一个函数,例如:

const greetJohn = (person: Person) => {
  console.log(greet(person));
};

greetJohn({ name: "John Doe", age: 30 }); // 输出:"Hello, John Doe!"

这样,函数greetJohn只能被调用,并且只能传入一个Person对象作为参数。

约束构造函数

接口也可以用来约束构造函数。例如,我们可以定义一个名为Car的接口,它定义了makemodelyear三个属性:

interface Car {
  make: string;
  model: string;
  year: number;
}

然后,我们可以使用这个接口来约束一个构造函数,例如:

class Car implements Car {
  make: string;
  model: string;
  year: number;

  constructor(make: string, model: string, year: number) {
    this.make = make;
    this.model = model;
    this.year = year;
  }
}

这样,类Car只能被实例化为一个具有makemodelyear属性的对象。

可以定义任意的属性

接口可以定义任意的属性。例如,我们可以定义一个名为Animal的接口,它定义了nameagespecies三个属性:

interface Animal {
  name: string;
  age: number;
  species: string;
}

然后,我们可以使用这个接口来定义一个对象,例如:

const animal: Animal = {
  name: "Spot",
  age: 5,
  species: "Dog"
};

这样,对象animal就具有nameagespecies三个属性。

可以索引属性

接口可以索引属性。例如,我们可以定义一个名为Dictionary的接口,它定义了一个索引属性,该索引属性可以接受一个字符串作为键,并返回一个字符串作为值:

interface Dictionary {
  [key: string]: string;
}

然后,我们可以使用这个接口来定义一个对象,例如:

const dictionary: Dictionary = {
  "apple": "A fruit",
  "banana": "Another fruit",
  "computer": "A machine"
};

这样,对象dictionary就具有一个索引属性,我们可以使用字符串作为键来访问该属性,并获取对应的值。

可以实现多个接口

接口可以实现多个接口。例如,我们可以定义一个名为Flyable的接口,它定义了fly()方法:

interface Flyable {
  fly(): void;
}

然后,我们可以定义一个名为Bird的接口,它继承了Flyable接口:

interface Bird extends Flyable {
  name: string;
  age: number;
}

这样,接口Bird就具有了Flyable接口的所有属性和方法,并且还具有了自己的nameage属性。

如果一个函数的类型拥有了其他属性

如果一个函数的类型拥有了其他属性,那么这个函数就可以被认为是一个接口。例如,我们可以定义一个名为Printable的接口,它定义了一个print()方法:

interface Printable {
  print(): void;
}

然后,我们可以定义一个名为Document的类,它实现了Printable接口:

class Document implements Printable {
  print() {
    console.log("Printing document...");
  }
}

这样,类Document就具有了Printable接口的所有属性和方法。

TypeScript中的泛型

泛型是TypeScript中的一种语法特性,它允许我们定义可重用的代码。泛型可以用于定义函数、类和接口。

泛型的使用

泛型可以使用尖括号<>来定义。例如,我们可以定义一个名为Array的泛型,它接受一个类型参数T,并表示一个由类型T的元素组成的数组:

interface Array<T> {
  [index: number]: T;
  length: number;
}

然后,我们可以使用这个泛型来定义一个数组,例如:

const numbers: Array<number> = [1, 2, 3, 4, 5];

这样,数组numbers就只能包含数字元素。

泛型与约束

泛型可以与约束一起使用。例如,我们可以定义一个名为Comparable的泛型,它接受一个类型参数T,并表示一个可以与另一个类型T的对象进行比较的对象:

interface Comparable<T> {
  compareTo(other: T): number;
}

然后,我们可以使用这个泛型来定义一个类,例如:

class Person implements Comparable<Person> {
  name: string;
  age: number;

  compareTo(other: Person): number {
    if (this.age < other.age) {
      return -1;
    } else if (this.age > other.age) {
      return 1;
    } else {
      return 0;
    }
  }
}

这样,类Person就具有了Comparable接口的所有属性和方法。

结语

接口和泛型是TypeScript中非常重要的两个特性。接口可以用来约束变量、函数和构造函数,还可以用来定义任意的属性和索引属性。泛型可以用来定义可重用的代码。本文对接口和泛型进行了详细的介绍,希望对读者有所帮助。