泛型Generice
泛型基本了解
- 泛型指代的是宽泛的类型,‘型’指代的是类型,‘泛’宽泛的,不确定的,泛型还是通过严格类型,去约束程序,
- 确定类型
let a:string = '确定类型' 1. 这个变量必须要传递的是字符串类型的数据
-
泛型,也是控制类型的,使用方式与类型相同,只不过类型是动态指定的类型
-
泛型允许我们给类型传递参数,也就是动态的设置某一个函数或者是属性设置‘类型’
1. 复用函数
function uname<T>(name: T): T {
return name
}
let str = uname<string>('泛型的基本使用')
console.log(str)
- ‘T’代表的是类型,并不是值,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
- 泛型也是可以自动推断类型的,如果不给他传递明确的类型,他会根据传入的值,去推断,值是什么的类型。
泛型的继承
使用泛型约束函数
function user<T>(num:T) : T {
return num.length
}
console.log(user<number>(5)) // 打印结果报错
为什么会出现类型‘T’上不存在length属性,原因是,‘T’类型他是我们动态传递的类型,并且‘num’没有明确的地方指出,它存在‘length’属性。也就是说,这个‘num’的类型可以是任意的类型,所以当使用函数者传递了‘number’类型,就会导致报错
- 解决方案(1)
1. 使用继承,继承其他类型,其他类型有这个属性,就不会报错了
function uname<T extends string>(num:T):number { 1. 返回值是number,是因为T继承了string类型
return num.length
}
console.log(uname<string>('lagou.com'));
- 解决多种类型的继承,解决方案
1. 使用联合类型,通过让T继承‘联合类型’
function uname<T extends any[] | string>( num:T ):number {
return num.length
}
console.log(uname<string>('lagou.com'));
console.log(uname<any[]>([1,2,3,4,5,6]));
- 如果一个函数的参数,一定是一个数组,那么他一定会有 length 属性,那么泛型这时候约束的不再是数组本身,而是数组中的元素,在传递类型的时候,传递什么类型,数组中的元素就是什么类型
function uname<T>(num:T[]): number {
return num.length
}
console.log(uname<number>([1,2,3,4,5,6,7]));
2. 如果想要数组里面允许存放‘数值类型和字符串类型’,我们可以使用联合类型声明
function uname<T>(num:T[]): number {
return num.length
}
console.log(uname<number | string>([1,2,3,4,5,6,7,'str']));
- ‘T’就是动态的类型,传递什么类型,他就是什么类型,如果在函数里面调用‘参数’里面的某一个属性,他不会成功,由于‘T’目前内部没有任何的‘类型约束’,他的类型来源于调用者的传递,所以起初会报错。在这种特殊的情况下使用‘继承’,继承其他类型,其他类型拥有这个属性,即可
类中使用泛型
class User<T> {
data:T[] = [];
public push(...item: T[]) {
return this.data.push(...item)
}
public shift():T {
return this.data.shift()
}
}
let user = new User<number>()
user.push(1,2,3,4,5,6,7)
user.shift()
构造函数中使用泛型
通过泛型,去约束构造函数接收或者是传递的数据,以确保程序的健壮性。
{
class User<T> {
private _u: T = null;
public constructor(n: T) {
this._u = n
}
public get(): T {
return this._u
}
}
interface StrUser {
name: string,
age: number
}
let user = new User<StrUser>({name:'小明',age: 18})
console.log(user.get());
}
接口中使用泛型
‘泛型’的多类型定义,多类型定义可以通过在【< T , B >】逗号的方式,创建多个‘泛型’,供给多个属性进行使用
{
interface User<B,C> {
title: string;
isLogin: B,
comments: C
}
type comments = {
phone:number
count: number
}
const str: User<boolean,comments> = {
title: '当前用户',
isLogin: true,
comments: {
phone: 666666,
count: 666666
}
}
console.log(str);
}