元组基础

元组跟数组的区别在于元组可以存储不同类型的元素

et tom:[string,number];

tom = ["name",18];

tom.push(18);
tom.push(18);
console.log(tom);
// tom.push(true);   //报错
tom[3] = 10   //报错,只能赋值tom[0],tom[1];

注意:

  1. 数组中的数据类型赋初值时必须和规定的类型顺序对应起来,多也不行,少也不行
  2. 当使用越界索引给数组赋值的时候,会使用联合类型(只要值是规定类型的某一种即可),此时不用在意顺序。
泛型基础

概念:泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

看如下语法:

function createArray<T>(length:number,value:T):Array<T>{
    let arr:T[]=[];
    for(let i:number=0;i<length;i++){
        arr.push(value);
    }
    return arr;
}

createArray<string>(10,"1");   //使用方式
  • createArray中的T代表函数输入类型
  • value:T代表此形参的类型为T,
  • :Array代表函数的返回值类型为T类型数组

多个类型参数语法:

function change<A,B>(a:A,b:B,c:A):A{  //可以用逗号,定义多个类型参数
    return a;
}
泛型约束

对传入的类型进行约束,使其必须拥有某些属性。比如说我要造个自我介绍方法,需要对方法传一个动物对象,方法体内这个动物会说出自己的姓名和年龄,利用泛型,可以这样做:

function self_introduce<T>(animal:T):void{
    console.log(animal.name); //报错
    console.log(animal.age);  //报错
}

由于传入的对象不一定具有name或age属性,此时就要对T进行约束,使其必须具有这两个属性,否则,让它报错。如下通过接口实现:

interface Animal{
    name:string,
    age:number
}

function self_introduce<T extends Animal>(animal:T):void{
    console.log(animal.name);
    console.log(animal.age);
}

// self_introduce({   //报错
//     name:"dog"
// });

self_introduce({
    name:"dog",
    age:18
});

通过接口限制传入对象的形状,T extends Animal,对泛型进行了约束

多个泛型之间的相互约束:

借助阮一峰老师的例子,助自己理解:

function copyFields<A extends B,B>(a:A,b:B):A{
    for(let i in b){
        a[i] = (<A>b)[i];  //用到了类型断言
    }
    return a;
}

console.log(copyFields({a:1,b:2},{a:2}));

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

泛型接口

旨在用接口的形式定义函数的形状(两种方式):

interface typeOne{    //第一种方式
    <T>(a:string,b:T):T
}

等价于:

interface typeOne<T>{
    (a:string,b:T):T
}
泛型类

旨在用来描述类中方法的形状,语法如下

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
    constructor(me:T,fn:(x: T, y: T) => T){  //源ts中文文档中提供的例子中没有这个构造函数,但是在我这里报错了,加上这个构造函数,正常编译
        this.zeroValue = me;
        this.add = fn;
    }
}

加油!!!!