剥丝抽茧,剖析TypeScript中的接口和泛型
2023-11-06 22:17:46
TypeScript中的接口
接口是TypeScript中的一种数据类型,它定义了对象的形状,即对象必须拥有的属性和方法。接口可以用来约束变量、函数和构造函数。
约束变量
接口可以用来约束变量。例如,我们可以定义一个名为Person
的接口,它定义了name
和age
两个属性:
interface Person {
name: string;
age: number;
}
然后,我们可以使用这个接口来约束一个变量,例如:
let person: Person = {
name: "John Doe",
age: 30
};
这样,变量person
只能被赋值为一个具有name
和age
属性的对象。
约束函数
接口也可以用来约束函数。例如,我们可以定义一个名为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
的接口,它定义了make
、model
和year
三个属性:
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
只能被实例化为一个具有make
、model
和year
属性的对象。
可以定义任意的属性
接口可以定义任意的属性。例如,我们可以定义一个名为Animal
的接口,它定义了name
、age
和species
三个属性:
interface Animal {
name: string;
age: number;
species: string;
}
然后,我们可以使用这个接口来定义一个对象,例如:
const animal: Animal = {
name: "Spot",
age: 5,
species: "Dog"
};
这样,对象animal
就具有name
、age
和species
三个属性。
可以索引属性
接口可以索引属性。例如,我们可以定义一个名为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
接口的所有属性和方法,并且还具有了自己的name
和age
属性。
如果一个函数的类型拥有了其他属性
如果一个函数的类型拥有了其他属性,那么这个函数就可以被认为是一个接口。例如,我们可以定义一个名为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中非常重要的两个特性。接口可以用来约束变量、函数和构造函数,还可以用来定义任意的属性和索引属性。泛型可以用来定义可重用的代码。本文对接口和泛型进行了详细的介绍,希望对读者有所帮助。