概述
泛型是一种编程语言特性,它允许我们在定义函数、类、接口等数据结构时使用参数化类型,从而实现更通用、灵活的代码。通过使用泛型,我们能够编写可以适用于多种数据类型的代码,而无需为每种数据类型编写重复的代码。
泛型的应用
泛型在函数中使用
根据参数不同,处理结果不同
const getArray = <T>(times: number, val: T): T[] => {
let result = [];
for (let i = 0; i < times; i++) {
result.push(val);
}
return result;
};
getArray(3, "a"); // ['abc','abc','abc'] 当我使用的时候可以确定类型
多个泛型也可以使用于元组交换
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
const originalTuple: [number, string] = [42, "hello"];
const swappedTuple: [string, number] = swap(originalTuple);
console.log(swappedTuple); // 输出:["hello", 42]
泛型接口的使用
可以定义泛型接口,使其能够适用于多种对象的结构。
// 1) 使用接口的时候确定的类型
type ICallback<T> = (item: T, idx: number) => void;
type IForEach = <T extends string | number>(
arr: T[],
callback: ICallback<T>
) => void;
// 2) 在调用函数的时候确定了类型
const forEach: IForEach = (arr, callback) => {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i); // callback 没有执行, 所以无法推导arr[i] = T
}
};
forEach(["a", "b", "c"], function (item) {
console.log(item);
});
泛型在类中使用
类接口, 描述类中的属性和方法。 求列表中的最大值 调用的时候可以限制传入的类型
class MyList<T extends number | string> {
private arr: T[] = [];
add(val: T) {
this.arr.push(val);
}
getMax(): T {
let arr = this.arr;
let max = arr[0];
for (let i = 0; i < arr.length; i++) {
let cur = arr[i];
cur > max ? (max = cur) : void null;
}
return max;
}
}
let list = new MyList();
list.add(1);
list.add(100);
默认泛型
场景就是如果用户不传入类型 我也希望有默认值
type Union<T = string> = T | number;
type t1 = Union;
type t2 = Union<boolean>;
此时type t1 = string | number,type t2 = number | boolean
泛型约束
泛型约束是 TypeScript 中的一种高级技术,允许你定义泛型类型参数的约束条件,以便在操作中保证类型的兼容性和类型安全性。通过泛型约束,你可以限制允许传递给泛型类型参数的数据类型范围,从而确保代码的正确性。
约束传入的泛型类型, A extends B,A是B的子类型.
function handle<T extends number | string>(val: T): T {
return val;
}
let r1 = handle(123);
let r2 = handle("abc");
上述其他场景也有应用泛型约束,总之,泛型约束是 TypeScript 中的一个重要概念,通过限制泛型类型参数的操作范围,它能够提高代码的类型安全性和可维护性。在实际开发中,泛型约束能够帮助我们编写更强大、更可靠的代码,同时减少潜在的错误。无论是限制特定数据类型的操作范围,还是为泛型接口添加额外功能,泛型约束都是编写高质量代码的有力工具。