接上篇。html
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 /*--------------------------------------------------------------------------*/
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,就不一樣了