泛型:指在定义函数、接口、类时,不预先指定具体的类型,而是在应用的时候在指定类型的一种个性。
一、泛型函数

//需要:封装一个函数,能够创立一个指定长度的数组,同时将每一项都填充一个默认值//1、应用any类型function getArr(val:any,len:number):any[]{    const arr:any[] = []    for(let i = 0; i<len; i++){        arr.push(val)    }    return arr}const arr1 = getArr('abcde',3)const arr2 = getArr(100.123,3)console.log(arr1) //["abcde", "abcde", "abcde"]console.log(arr2) //[100.123, 100.123, 100.123]//应用any类型后,会呈现TS动态查看体现不了的毛病,因而能够应用泛型来解决//2、应用泛型 function getArr2<T>(val:T,len:number): T[]{    const arr:Array<T> = []    for(let i = 0; i<len; i++){        arr.push(val)    }    return arr}//在调用函数时,应用<>手动指定类型,即便不指定类型,ts也会主动推论出数据的类型const arr3 = getArr2<number>(100.123,3)const arr4 = getArr2<string>('abc',3)

多个泛型参数的函数:函数中有多个泛型的参数

function getMsg<K,V>(key:K,value:V){    return [key,value]} const arr = getMsg<string,number>('age',18)console.log(arr) //['age',18]

二、泛型接口
在定义接口时,为接口中的属性或办法定义泛型类型,在应用接口时,再指定具体的泛型类型。
类的泛型接口

//定义一个泛型接口-类interface IBaseCRUD<T>{    data: T[] //含有data属性,一个元素类型为T的数组,用来存储数据信息    add:(t:T)=>void //含有增加数据信息的办法    getById: (id: number) => T //含有查找数据信息的办法}//定义一个人类信息的类class Person{    id?:number    name: string    age: number    constructor(name:string,age:number){        this.name = name        this.age = age    }}//定义一个满足IBaseCRUD接口可增加查找人类信息的类class PersonCRUD implements IBaseCRUD<Person>{    data: Array<Person> = [] //初始化    add(person:Person):void{        //主动生成id        //person.id = Date.now()+Math.random()        person.id = this.data.length//测试        //向data中增加人类信息        this.data.push(person)    }    getById(id:number):Person{        return this.data.find(person=>person.id === id)    }}//实例化PersonCRUDconst personCRUD = new PersonCRUDpersonCRUD.add(new Person('Liane',18))personCRUD.add(new Person('Ann',16))console.log(personCRUD.data)//[Person {name: "Liane", age: 18, id: 0},Person {name: "Ann", age: 16, id: 1}]console.log(personCRUD.getById(0))//Person {name: "Liane", age: 18, id: 0}

函数的泛型接口

//定义一个函数的泛型接口interface IGetArr<T>{    (val:T,len:number):Array<T>}//定义一个合乎IGetArr接口的函数--注:必须注明接口的类型let getArr:IGetArr<any> = function<T>(val:T,len:number){    let result:T[] = []//默认值为[]    for(let i = 0; i<len; i++){        result[i] = val    }    return result}//调用函数时不可能指定类型,否则会提醒谬误,因为该函数类型曾经是接口类型了console.log(getArr<string>('a',3))//提醒谬误console.log(getArr('a',3))//['a','a','a']console.log(getArr(123,3))//[123,123,123]

三、泛型类
一个类中的属性值的类型不确定,办法中的参数及返回值类型不确定的状况,能够定义泛型类

//定义一个泛型类class GenericNumber<T> {    zeroValue: T;    add: (x: T, y: T) => T;}let myGenericNumber = new GenericNumber<number>();myGenericNumber.zeroValue = 0;myGenericNumber.add = function(x, y) { return x + y; }; 

四、泛型束缚
在函数外部应用泛型变量的时候,因为当时不晓得它是那种类型,所以不能随便操作它的属性和办法。

function loggingIdentity<T>(arg: T): T {    console.log(arg.length);    return arg;}// index.ts(2,19): error TS2339: Property 'length' does not exist on type 'T'.

上例中,泛型 T 不肯定蕴含属性 length,所以编译的时候报错了。

这时,咱们能够对泛型进行束缚,只容许这个函数传入那些蕴含 length 属性的变量。这就是泛型束缚:

interface Lengthwise {    length: number;}function loggingIdentity<T extends Lengthwise>(arg: T): T {    console.log(arg.length);    return arg;} 

上例中,咱们应用了 extends 束缚了泛型 T 必须合乎接口 Lengthwise 的形态,也就是必须蕴含 length 属性。

此时如果调用 loggingIdentity 的时候,传入的 arg 不蕴含 length,那么在编译阶段就会报错了:

interface Lengthwise {    length: number;}function loggingIdentity<T extends Lengthwise>(arg: T): T {    console.log(arg.length);    return arg;}loggingIdentity(7);// index.ts(10,17): error TS2345: Argument of type '7' is not assignable to parameter of type 'Lengthwise'. 

多个类型参数之间也能够相互束缚:

function copyFields<T extends U, U>(target: T, source: U): T {    for (let id in source) {        target[id] = (<T>source)[id];    }    return target;}let x = { a: 1, b: 2, c: 3, d: 4 };copyFields(x, { b: 10, d: 20 }); 

上例中,咱们应用了两个类型参数,其中要求 T 继承 U,这样就保障了 U 上不会呈现 T 中不存在的字段。