TypeScript入门笔记(二)
接上篇。
TypeSrcipt 泛型
1 /*---------------------------------0.引子-----------------------------------*/ 2 /*现在很多语言里也有泛型的概念,也没啥好说的,简单的例子一个,主要就是看泛型在ts中的写法*/ 3 function getInfo<T>(params: T): T { 4 return params; 5 } 6 //调用泛型方法 7 let output_str = getInfo<string>("str"); 8 //简单的写法:而且ts的编译器能够自动帮我们推断类型 9 let output_num = getInfo(100); 10 /*--------------------------------------------------------------------------*/ 11 12 /*--------------------------------1.泛型参数---------------------------------*/ 13 //方法参数使用泛型,类型是指定类型的数组 14 function getMax<T>(arr: Array<T>): T { 15 let max = arr[0]; 16 arr.forEach(item => { 17 if (item > max) { 18 max = item; 19 } 20 }); 21 return max; 22 } 23 let numArr: Array<number> = [2, 3, 44, 1, 9, 10]; 24 let numStr: Array<string> = ['c', 'd', 'a', 'A']; 25 26 console.log(getMax(numArr)); //44 27 console.log(getMax(numStr)); //d 28 /*--------------------------------------------------------------------------*/ 29 30 /*--------------------------------2.泛型接口----------------------------------*/ 31 //在ts中就不要使用I做为接口名前缀了,这不是人家的规范 32 interface GetMinFn { 33 <T>(arg: Array<T>): T 34 } 35 /* 其实我更喜欢这么写 36 interface GetMin<T> { 37 (arg: Array<T>): T 38 } 39 */ 40 41 //写一个方法 42 function getMin<T>(arr: Array<T>): T { 43 let min = arr[0]; 44 arr.forEach(item => { 45 if (item < min) { 46 min = item; 47 } 48 }); 49 return min; 50 } 51 //用接口来接方法 52 let myGetMinFunction: GetMinFn = getMin; 53 console.log(myGetMinFunction(numArr)); //1 54 /*--------------------------------------------------------------------------*/ 55 56 /*--------------------------------3.泛型类-----------------------------------*/ 57 //跟泛型接口大差不差 58 class MySort<T>{ 59 private dataCollection: Array<T> = new Array<T>(); 60 61 constructor(arr?: Array<T>) { 62 if (arr) { 63 this.dataCollection = arr; 64 } 65 } 66 67 add(data: T): void { 68 this.dataCollection.push(data); 69 } 70 71 min(): T { 72 return getMin<T>(this.dataCollection); 73 } 74 75 max(): T { 76 return getMax<T>(this.dataCollection); 77 } 78 } 79 //实例化泛型类,需要传入类型参数 80 let numberSortObj = new MySort<number>(numArr); 81 let stringSortObj = new MySort<string>(numStr); 82 83 console.log(numberSortObj.min()); //1 84 console.log(numberSortObj.max()); //44 85 console.log(stringSortObj.min()); //A 86 console.log(stringSortObj.max()); //d 87 /*--------------------------------------------------------------------------*/ 88 89 /*--------------------------------4.泛型约束---------------------------------*/ 90 //就是T代表的类型不是所有类型都可以的,需要满足一定的条件,这个条件就称为“泛型约束” 91 //比如下面的函数,想获取传入的变量的长度,但是不是所有的类型都有“长度”这个属性的 92 // function getLength<T>(arg: T): T { 93 // console.log(arg.length); // Error: T一定就有".length"这个属性 94 // return arg; 95 // } 96 97 interface Lengthwise { 98 length: number; 99 } 100 //传入的参数必须满足接口 Lengthwise 的约束,约束就是必须有一个名为length的属性,并且返回 101 //值是number类型 102 function getLength<T extends Lengthwise>(arg: T): T { 103 console.log(arg.length); // OK 104 return arg; 105 } 106 107 //现在这个泛型方法传入的参数类型就得到了约束 108 //getLength(3); //Error:Argument of type '3' is not assignable to parameter 109 //of type 'Lengthwise'. 110 getLength([1, 2, 3, 4, 5]); //5 111 getLength({ length: 10, value: 3 }); //10 112 113 /*--------------------------------------------------------------------------*/
TypeSrcipt 类型兼容性
1 //类型兼容性的话我们在其他语言(C#或者Java)中也都接触过,举几个典型例子 2 3 /********************************1. “接口”接收“类”*******************************/ 4 interface Named { 5 name: string; 6 } 7 8 class People { 9 name: string; 10 constructor(n: string) { 11 this.name = n; 12 } 13 } 14 15 let p: Named = new People("sherlock"); 16 17 //****2. "接口"接收对象,只要包含name属性即可,编译器检查的过程是递归进行的,检查每个成员及子成员。**** 18 //****所以说TypeScript是结构性的类型系统,咱对比两个类型是否相同就看你的内部结构是否一样************* 19 let alice: Named; 20 let aliceProfile = { name: 'Alice', location: 'Seattle' }; 21 //变量aliceProfile中包含name属性 22 alice = aliceProfile; 23 24 //********************************3. 同上,方法参数也可以是接口******************************** 25 function sayHello(n: Named) { 26 console.log('Hello, i am ', n.name); 27 } 28 sayHello(aliceProfile); 29 30 //********4. 比较两个函数,强类型语言中很少有这样的写法,但是在js中函数也是一种特殊对象,**************** 31 //********这样就好理解了,你可以对比到子类型和父类型 32 let a = (a: number) => 0; 33 let b = (b: number, s: string) => 0; 34 35 a = b; // 报错 36 b = a; // OK 37 38 let c = () => ({ name: 'Alice' }); 39 let d = () => ({ name: 'Alice', location: 'Seattle' }); 40 41 c = d; // OK 42 d = c; // 报错, 系统强制源函数的返回值类型必须是目标函数返回值类型的子类型 43 44 45 //********************************5. 不同的枚举类型之间是不兼容的******************************** 46 enum Status { Ready, Waiting }; 47 enum Color { Red, Blue, Green }; 48 49 let s = Status.Ready; 50 s = Color.Green; // Error 51 52 //********6. 比较两个类类型的对象时,只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内*********** 53 //********并且变量的可访问等级也要是相同的 54 class Beauty { 55 eyes: number = 2; 56 constructor(name: string, height: number) { } 57 } 58 59 class Ugly { 60 eyes: number = 2; 61 constructor(height: number) { } 62 } 63 64 let jack: Beauty = new Beauty("jack", 190); 65 let jordan: Ugly = new Ugly(140); 66 67 jack = jordan; // OK 68 jordan = jack; // OK 69 70 //********************************7. 再看一下泛型********************************************* 71 interface Empty<T> { 72 } 73 74 let eNum: Empty<number>; 75 let eStr: Empty<string>; 76 77 eNum = eStr; // OK, 因为Empty<T>这个接口中的“结构”都是空的,所以这两个就是兼容的 78 79 interface NotEmpty<T> { 80 data: T; 81 } 82 let neNum: NotEmpty<number>; 83 let neStr: NotEmpty<string>; 84 85 neNum = neStr; // Error, 这种情况下两个对象中的“结构”一个是number型一个是string,就不同了