好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

TypeScript入门笔记(三)

接 上篇 。

   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  }

 

查看更多关于TypeScript入门笔记(三)的详细内容...

  阅读:48次