元组基础
元组跟数组的区别在于元组可以存储不同类型的元素
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];
注意:
- 数组中的数据类型赋初值时必须和规定的类型顺序对应起来,多也不行,少也不行
- 当使用越界索引给数组赋值的时候,会使用联合类型(只要值是规定类型的某一种即可),此时不用在意顺序。
泛型基础
概念:泛型(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;
}
}
加油!!!!