泛型函数
// 普通写法
// function firstElement(arr:any[]){
// return arr[0]
// }
// 等价
function firstElement<Type>(arr:Type[]):Type|undefined{
return arr[0]
}
console.log(firstElement([1,2,3]));
console.log(firstElement(['a','b',"c"]));
使用受限
function restriction <Type extends {length : number}>(
obj:Type,
num: number,
arr?:Type
):Type|undefined{
if(obj.length<num){
return obj
}
return arr
// return obj.length
}
// 返回这个值必须得是泛型类型的数据
// 扩展的数据类型也不能使用此方法做为扩展,因为这需要它们来自具有泛化能力的类型。
// console.log(restriction( [1,2,3,'a','b','c',3],10));
console.log(restriction( [1,2,3,'a','b','c',3],10,[1]));
// 错例如下
// function restriction <Type extends {length : number}>(
// obj:Type,
// num: number,
// ):Type|undefined{
// if(obj.length<num){
// return obj
// }
// return obj.length
// }
// // console.log(restriction( [1,2,3,'a','b','c',3],10));
// console.log(restriction( [1,2,3,'a','b','c',3],10,[1]));
限制条件
function longest <Type extends {length:number}>(a:Type,b:Type){
if(a.length>b.length){return a;
}
return b
}
let sta=longest([10,20,3,123,123,123,132], [12,123,12,12,3,123,235,23,45,34,])
console.log(sta);
函数重载
function makeDate(timestamp:number ):Date;
function makeDate(year:number,month:number,day:number):Date
// 以上都是重载签名
// 实现签名
// 第二个重载的参数必须加问号 有点逻辑短路的意思
function makeDate(timestamp:number,year?:number,day?:number):Date {
if(year&&day){
return new Date(year,timestamp,day)
}
return new Date(timestamp)
}
const d1=makeDate(1582,10,5)
const d2=makeDate(123123123)
console.log(d1,d2);
// 定义了几个就传几个,这里要么传三个 要么传一个
指定类型参数
function combine<T>(arr:T[],arr2:T[]):T[]{
return arr.concat(arr2)
}
console.log(combine([1,2,3],[4,5,6]));
回调可选参数
// 回调写一个函数类型,不要写可选参数,除非打算在不传递该参数的情况下才调用函数
function myForEach(arr:any[],callback:(arg:any,index?:number)=>void){
for(let i=0 ;i<arr.length;i++){
callback(arr[i],i)
}
}
let arr=myForEach(['foo', 'bar', 'baz'],(val,i)=>{
console.log(val,i)
// 在这里如果要用i不加问号就会报错 按照上面定义的执行
i?.toFixed
})
编写通用函数的准则
// 1 可能的情况下使用类型参数本身,而不是对其进行约束
// 2尽可能少使用类型参数
// 3如果一个类型的参数只能出现在一个地方,考虑是否需要
function firstElement1<T>(arr:T[]){
return arr[0]
}
// 都是第一种比较好 下面的难以推断没有什么意义
function firstElement2<T extends any[]>(arr:T){
return arr[0]
}
firstElement1([1,2,3])
firstElement2([1,2,3])
function filter1<T>(arr:T[], fn: (arg:T)=>boolean){
return arr.filter(fn)
}
function filter2<T ,FN extends (arg:T)=>boolean>(arr:T[], fn:FN){
return arr.filter(fn)
}
function greet1<S extends string>(s:S){
console.log('hello'+s);
}
function greet2<S>(s:string){
console.log('hello'+s);
}
greet1('world')
greet2('world')