接 上篇 。
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://www.haodehen.cn/did223475