泛型是Ts中较为重要的一环,TypeScript 中的泛型允许你在定义函数、类或接口时,不指定具体类型,而在使用时再动态地传入类型参数,使得代码更加灵活和可重用性更高。
1.基本语法
在 TypeScript 中,泛型通常用尖括号(<>)括起来表示类型参数,可以包括一个或多个类型参数。例如:
function identity<T>(arg: T): T {
return arg
}
这里 <T>
表示类型参数,可以传入任何类型,返回值类型与传入的参数类型相同。
在使用泛型时,我们可以指定具体的类型参数,也可以让编译器根据上下文自动推断类型。例如:
let result1 = identity<string>("hello"); // result1 类型为 string
let result2 = identity(42); // result2 类型为 number
除了在函数中使用泛型,我们也可以在类、接口等代码结构中使用泛型。
2.泛型接口
泛型接口的定义方式和普通接口基本相同,只是在定义时需要在接口名后面加上尖括号,尖括号内为泛型类型参数。例如:
interface MyArray<T> {
push(item: T): void;
pop(): T | undefined;
length: number;
}
上面的代码定义了一个泛型接口 MyArray<T>
,其中的方法 push
接受一个泛型类型参数 T
的参数,并且返回值为 void
;方法 pop
没有参数,返回一个 T
类型的值或者 undefined
;属性 length
返回一个 number
类型的值。
通过这种方式,我们可以定义出具有通用性的接口,以适应多种不同的数据类型。在实际使用时,我们需要指定泛型类型参数的具体类型。例如:
const myArr: MyArray<string> = {
push(item: string) {
// ...
},
pop() {
// ...
},
length: 0
};
上面的代码定义了一个 MyArray<string>
类型的变量 myArr
,其中泛型类型参数 T
被指定为 string
。这个变量可以被用来操作一个字符串类型的数组,因为它符合了 MyArray
接口的定义。
3.泛型类
泛型类是一种在类定义时使用类型变量的方式,可以在类的属性、方法和构造函数中使用这个类型变量。与泛型函数类似,泛型类的类型变量可以在使用时指定具体的类型,从而实现类的复用和通用性。
泛型类的语法和普通类的语法类似,只是在类名后面使用尖括号定义泛型参数,例如:
class MyClass<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
这个例子定义了一个名为 MyClass 的泛型类,它有一个类型参数 T。在类的构造函数和方法中都可以使用这个类型参数,例如在构造函数中将传入的参数值赋值给类的私有属性 value,以及在 getValue 方法中返回这个属性值。
使用泛型类时需要在类名后面使用尖括号传入具体的类型,例如:
const myInstance = new MyClass<string>("Hello World");
console.log(myInstance.getValue()); // 输出 "Hello World"
在这个示例中,我们创建了一个 MyClass 的实例 myInstance,并将类型参数指定为 string。在实例中调用 getValue 方法时,返回的是构造函数中传入的 "Hello World" 字符串值。
除了使用单一的类型参数外,泛型类还可以使用多个类型参数,例如:
class Pair<A, B> {
constructor(public first: A, public second: B) {}
swap(): Pair<B, A> {
return new Pair(this.second, this.first);
}
}
这个例子定义了一个名为 Pair 的泛型类,它有两个类型参数 A 和 B,表示这个类包含了两个值的对,第一个值的类型是 A,第二个值的类型是 B。在构造函数中使用这两个类型参数分别定义了类的两个公有属性 first 和 second。
Pair 类还实现了一个 swap 方法,这个方法会交换 Pair 实例中两个值的顺序,并返回一个新的 Pair 实例,其中第一个值的类型变为了 B,第二个值的类型变为了 A。这个方法的返回类型中使用了泛型参数,表示返回的实例的类型与调用 swap 方法的实例的类型相同,只是两个类型参数的顺序交换了。
使用 Pair 类时可以传入任意两个类型作为类型参数,例如:
const myPair = new Pair<string, number>("hello", 42);
console.log(myPair.first); // 输出 "hello"
console.log(myPair.second); // 输出 42
const swappedPair = myPair.swap();
console.log(swappedPair.first); // 输出 42
console.log(swappedPair.second); // 输出 "hello"
上面的示例定义了一个泛型类Pair<T, U>
,这个类有两个类型参数T和U,代表这个类可以接受任意两个类型作为其类型参数。这个类有两个属性first
和second
,分别是类型为T和类型为U的值。类中的构造函数需要传入两个参数,一个是类型为T的值,一个是类型为U的值,然后将这两个值分别赋给first
和second
属性。此外,这个类还有一个方法swap
,可以将first
和second
属性的值互换。使用时需要指定T和U的具体类型,例如const p = new Pair<string, number>("foo", 123)
,表示实例化一个Pair类,其类型参数T为string类型,U为number类型,然后将"foo"赋给first
属性,将123赋给second
属性。