TypeScript是JavaScript的超集,它添加了静态类型、类、接口和其他许多功能,以提供更好的代码质量和更强大的开发体验。其中,泛型是TypeScript的一个重要特性,它允许我们编写更灵活、更通用的代码。
泛型的使用
在TypeScript中,泛型可以用于类、接口、函数和方法等。
泛型类
以下是一个泛型类的例子:
class Box<T> {
content: T;
constructor(content: T) {
this.content = content;
}
get() {
return this.content;
}
}
在这个例子中,Box是一个泛型类,其类型参数为T。这个类有一个属性content,其类型为T,并且有一个构造函数,它接受一个类型为T的参数。此外,这个类还有一个get方法,它返回content的值。
你可以像下面这样使用这个类:
let a = new Box<string>("Hello");
let b = new Box<number>(123);
console.log(a.get()); // "Hello"
console.log(b.get()); // 123
泛型接口
以下是一个泛型接口的例子:
interface Generator<T> {
(): T;
}
在这个例子中,Generator是一个泛型接口,它定义了一个返回类型为T的方法。你可以像下面这样使用这个接口:
function identity<T>(arg: T): T {
return arg;
}
type Identity<T> = (arg: T) => T;
console.log(identity<string>("Hello")); // "Hello"
console.log((<Identity<number>>identity)(123)); // 123
类型约束
当你在使用泛型时,有时可能需要更具体的类型。这时,你可以使用类型约束。例如:
class Box<T extends string | number> {
content: T;
constructor(content: T) {
this.content = content;
}
get() {
return this.content;
}
}
在这个例子中,Box的content的类型被限制为字符串或数字。这意味着你不能将其他类型的值传递给content。例如:
let a = new Box<string>("Hello"); // 正确
let b = new Box<number>(123); // 正确
let c = new Box<boolean>(true); // 错误,类型 'boolean' 不符合期望类型 'string | number'。
此外,你还可以在泛型中使用其他泛型。例如:
class Pair<T, U> {
first: T;
second: U;
constructor(first: T, second: U) {
this.first = first;
this.second = second;
}
}
在这个例子中,Pair是一个有两个类型参数的泛型类。你可以像下面这样使用这个类:
let a = new Pair<string, number>("Hello", 123); // 正确
let b = new Pair<number, string>(123, "Hello"); // 正确
除了上述的例子,泛型还可以在许多其他情况下使用,例如泛型函数、泛型方法、泛型索引等等。
泛型函数可以接受泛型参数,并返回泛型结果。例如,下面的函数可以接受一个数组和一个索引,并返回该索引处的元素。
tfunction getItem<T>(array: T[], index: number): T {
return array[index];
}
泛型方法也可以接受泛型参数,并返回泛型结果。例如,下面的方法可以接受一个对象和一个键,并返回该键对应的值。
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
泛型索引可以用于定义可以使用字符串作为索引的接口。例如,下面的接口可以接受一个字符串作为索引,并返回对应的值。
interface Dictionary<T> {
[index: string]: T;
}
除了上述的例子,泛型还有很多其他的应用场景。总的来说,泛型使得代码更加灵活和通用,可以用于处理许多不同类型的情况。同时,由于类型约束的存在,代码也更加安全。