接 上篇 。
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,就不同了
查看更多关于TypeScript入门笔记(二)的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did223475