泛型 Generic
泛型是指定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性.
有这样一个函数handle,接收一个参数,number数组或者string数组,并返回数组中的最小值。
let handle = (arr: any[]): any => {
var min=arr[0];
arr.forEach((value)=>{
if(value<min){
min=value;
}
});
return min;
}
console.log(handle(["blue","red","green","pick"]))// blue
console.log(handle([13.4, 2.2, 3.6, 46.5, 85.8]))//2.2
上面函数handle由于不确定参数传入的类型,所以将类型都规定为any,虽然满足了需求,却丢失了对类型的检测,比如以下代码:
let value = handle([1,2,3,4,5])
value.split(",") // 跳过了类型检查,浏览器报错Uncaught TypeError: value.split is not a function,
value = handle(["h","e","l","l","o"])
value.toFixed() // 跳过了类型检查,浏览器报错Uncaught TypeError: value.toFixed is not a function
所以我们就需要使用泛型,泛型可以使我们的API支持多种类型数据以及多种类型的数据检查, 更好的约束API使用者规范的使用我们的插件或者库。
//把handle方法使用泛型改写下
let handle1 = <T>(arr: T[]): T => {
var min=arr[0];
arr.forEach((value)=>{
if(value<min){
min=value;
}
});
return min;
}
let value1 = handle1<Number>([13.4, 2.2, 3.6, 46.5, 85.8])
value1.split(",") // 类型检查,类型“number”上不存在属性“split”
console.log(value1.toFixed()) // 2
let value2 = handle1<String>(["blue","red","green","pick"])
value2.toFixed() // 类型检查,属性“toFixed”在类型“string”上不存在
console.log(value2.split('')) // ["b", "l", "u", "e"]
泛型函数
let handle2 = <T>(arr: T[]): T => {
var min=arr[0];
arr.forEach((value)=>{
if(value<min){
min=value;
}
});
return min;
}
let value3 = handle2<Number>([13.4, 2.2, 3.6, 46.5, 85.8])
泛型接口
interface Interface{
<T>(arr: T[]):T,
}
// 泛型变量也可以提到接口定义上, 这样接口里就都可以使用泛型变量了
interface Interface1<T>{
(arr: T[]):T
}
泛型约束:使用 extends指定泛型类型的继承关系。
interface HasLength {
length: number;
}
function handle3<T extends HasLength>(arg: T): T {
console.log(arg.length);
return arg;
}
handle3({ length: 2, value: 3 }); //传入参数必须有length属性
在泛型参数中使用类型参数。
规定参数propName必须是obj中的一员。
const getProps = <T, K extends keyof T>(obj: T, propName: K) =>{
return obj[propName]
}
const objs = {
a:'a',
b:'b'
}
getProps(objs, 'a') // 'a'
// getProps(objs, 'c') // 类型“"c"”的参数不能赋给类型“"a" | "b"”的参数