TypeScript入门笔记,二

上篇

  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,就不同了