TypeScript入門筆記(三)

上篇html

高級類型

  1 /*===============================類型斷言======================================*/
  2 /*C#中能夠使用as或者強轉的方法,雖然ts中也有相似的寫法,可是類型斷言
  3 只會影響 TypeScript 編譯時的類型,類型斷言語句在編譯結果中會被刪除*/
  4 
  5 //基接口
  6 class Animal {
  7     constructor(readonly name: string) {
  8     }
  9     eat(): void {
 10         console.log(`${this.name} is eating`);
 11     };
 12 }
 13 //子接口們
 14 class Dog extends Animal {
 15     roar(): void {
 16         console.log(`${this.name} is wongwongwong`);
 17     };
 18 }
 19 class Bird extends Animal {
 20     fly(): void {
 21         console.log(`${this.name} is flying`);
 22     };
 23 }
 24 class Fish extends Animal {
 25     swim(): void {
 26         console.log(`${this.name} is swimming`);
 27     };
 28 }
 29 //參數使用父類能夠接收全部子類
 30 function letsEat(animal: Animal) {
 31     animal.eat();
 32 }
 33 letsEat(new Dog("小魚"));    //小白 is eating
 34 
 35 // 在ts中,父類能夠斷言成子類,由於「狗狗確定是動物」很好理解
 36 function dog2Animal(xb: Dog) {
 37     (xb as Animal).eat()
 38 }
 39 
 40 //函數參數若是使用聯合類型,那麼能夠調用其動物類的方法
 41 function letsEat2(animal: Dog | Bird | Fish) {
 42     animal.eat();
 43 }
 44 letsEat(new Fish("小白"));   //小白 is eating
 45 
 46 //那麼想調用子類的方法的話,咱們能夠先進行類型斷言,父類能夠被斷言爲爲子類!
 47 //?:那若是animal斷言成Dog,可是animal的實際類型不是Dog,那會怎麼樣呢?
 48 function letRoar(animal: Animal) {
 49     (animal as Dog).roar();
 50 }
 51 function letsFly(animal: Dog | Bird | Fish) {
 52     (animal as Bird).fly();
 53 }
 54 //結果就是ts編譯沒問題,可是實際運行會報錯
 55 //letRoar(new Fish("小魚"));    //Error: animal.swim is not a function
 56 //letsFly(new Dog("小白"));     //Error: animal.fly is not a function
 57 
 58 //解決這個狀況能夠使用intanceof方法先判斷
 59 function letsPlay(animal: Dog | Bird | Fish) {
 60     if (animal instanceof Dog) {
 61         (animal as Dog).roar();
 62     }
 63     else if (animal instanceof Bird) {
 64         (animal as Bird).fly();
 65     } else if (animal instanceof Fish) {
 66         (animal as Fish).swim();
 67     }
 68 }
 69 letsPlay(new Bird("小鳥"));    //小白 is flying
 70 
 71 //  總結(https://ts.xcatliu.com/basics/type-assertion)
 72 // (1)聯合類型能夠被斷言爲其中一個類型;
 73 // (2)父類能夠被斷言爲子類;
 74 // (3)任何類型均可以被斷言爲 any;
 75 // (4)any 能夠被斷言爲任何類型;
 76 //  總之,若 A 兼容 B,那麼 A 可以被斷言爲 B,B 也能被斷言爲 A
 77 //  注意:類型斷言不是類型轉換
 78 
 79 
 80 /*===============================交叉類型======================================*/
 81 //交叉類型是將多個類型合併成一個類型的意思
 82 //例如, Person & Serializable & Loggable 這個類型的對象同時擁有了這三種類型的成員。
 83 
 84 /*for-in語法:能夠遍歷一個對象中的全部屬性,並以字典的讀取方式獲取屬性的值,語法:
 85     for (const prop in object) {
 86         if (object.hasOwnProperty(prop)) {
 87             const element = object[prop];
 88         }
 89     }
 90 */
 91 
 92 //如何建立混入的一個方法
 93 function extend<T1, T2 extends object>(type1: T1, type2: T2): T1 & T2 {
 94     let result = <T1 & T2>{};
 95 
 96     for (let prop in type1) {
 97         (<any>result)[prop] = type1[prop];
 98     }
 99 
100     for (let prop in type2) {
101         if (type2.hasOwnProperty(prop)) {
102             (<any>result)[prop] = (<any>type2)[prop]
103 
104         }
105     }
106     return result;
107 }
108 //在建立一個類類型
109 class Identity {
110     constructor(public gender: string, public birthDay: Date) {
111     }
112 }
113 //將Dog類和Identity類進行交叉
114 let bd: Date = new Date('2015-09-07');
115 let xb = extend(new Dog("小白"), new Identity("male", bd));
116 
117 console.log(xb.birthDay);   //2015-09-07
118 console.log(xb.gender);     //male
119 xb.roar();                  //小白 is wongwongwong
120 
121 
122 /*==============================能夠爲null的類型================================*/
123 //默認狀況下,類型檢查器認爲 null與 undefined能夠賦值給任何類型。
124 //按照JavaScript的語義,TypeScript會把 null和 undefined區別對待
125 
126 let s = "foo";
127 //s = null; // 錯誤, 'null'不能賦值給'string'
128 
129 let sn: string | null = "bar";
130 sn = null; // 能夠
131 
132 //sn = undefined; // error, 'undefined'不能賦值給'string | null'
133 
134 //對於可爲null類型的參數
135 function f(sn: string | null): string {
136     if (sn == null) {
137         return "default";
138     }
139     else {
140         return sn;
141     }
142 }
143 /* 「短路運算符」寫法:
144     function f(sn: string | null): string {
145         return sn || "default";
146     }
147  */
148 
149 
150 /*==============================字符串字面量類型================================*/
151 //字符串字面量:用來約束取值只能是某幾個字符串中的一個。
152 
153 type pet = 'dog' | 'bird' | 'fish';
154 function adoptPet(p: pet): Animal {
155     if (p === 'dog') {
156         return new Dog("小白");
157     }
158     else if (p === 'bird') {
159         return new Bird("飛飛");
160     }
161     else if (p === "fish") {
162         return new Fish("金金");
163     }
164     else {
165         assertNever(p);     //這招叫「完整性檢查」,本身體會,驚喜的是,若是前面條件判斷有漏掉某個情形,這裏是會報錯的。
166     }
167 }
168 function assertNever(x: never): never {
169     throw new Error("Unexpected object: " + x);
170 }
171 
172 adoptPet("bird");      //輸入的參數只能是「dog」「fish」「bird」之一
173 //adoptPet("cat");     //Error: 傳入其餘值會報錯
174 
175 //上面的例子用switch-case寫代碼看起來更清晰簡練一點
176 function adoptPetAgain(s: pet) : Animal {
177     switch (s) {
178         case "dog": return new Dog("小白"); 
179         case "bird": return new Bird("飛飛");
180         case "fish": return new Fish("金金");
181         default: return assertNever(s);
182     }
183 }
相關文章
相關標籤/搜索