zoukankan      html  css  js  c++  java
  • 013 --TypeScript之高级类型

    交叉类型可以简单理解为将多个类型合并成一个类型

    function extend<T, U>(first: T, second: U): T & U {
      let result = {} as T & U 
      for(let id in first) {
        result[id] = first[id] as any
      }
    
      for(let id in second){
        if(!result.hasOwnProperty(id)){
          result[id] = second[id] as any
        }
      }
      return result
     }
     //为了编译通过,我们让上述的first[id],second[id]断言成了any
     
     class Person {
       constructor(public name: string){
    
       }
     }
    
     interface loggable {
       log(): void
     }
    
     class ConsoleLogger implements loggable {
      log(){
    
      }
     }
    
     var jim = extend(new Person('jim'), new ConsoleLogger())
     //通过extend函数使两个class扩展到一起,称为交叉类型
     jim.name
     jim.log()

    编译后

    function extend(first, second) {
        var result = {};
        for (var id in first) {
            result[id] = first[id];
        }
        for (var id in second) {
            if (!result.hasOwnProperty(id)) {
                result[id] = second[id];
            }
        }
        return result;
    }
    //为了编译通过,我们让上述的first[id],second[id]断言成了any
    var Person = /** @class */ (function () {
        function Person(name) {
            this.name = name;
        }
        return Person;
    }());
    var ConsoleLogger = /** @class */ (function () {
        function ConsoleLogger() {
        }
        ConsoleLogger.prototype.log = function () {
        };
        return ConsoleLogger;
    }());
    var jim = extend(new Person('jim'), new ConsoleLogger());
    //通过extend函数使两个class扩展到一起,称为交叉类型
    jim.name;
    jim.log();

    联合类型

    function padLeft(value: string, padding: any/*string | number */) {
      if(typeof padding === 'number'){
        return Array(padding + 1).join(' ') + value
      } 
      if(typeof padding === 'string') {
        return padding + value
      }
      throw new Error(`Expected string or number got ${padding}`)
    }
    
    console.log(padLeft('Hello world', 5))//     Hello world
    console.log(padLeft('Hello world', '123'))//123Hello world
    //console.log(padLeft('Hello world', true))//这样写也不会报错,因为padding是any
    //什么是联合类型呢,就是如果给padding做约束,就是padding: string | number

    联合类型和交叉类型的区别是什么?联合类型是几种之一,交叉类型是几种类型之和

    interface Bird {
      fly()
    
      layEggs()
    }
    
    interface Fish {
      swim()
    
      layEggs()
    }
    
    function getSmallPet(): Fish | Bird {
      return //...
    }
    
    let pet = getSmallPet()
    pet.layEggs()
    //pet.swim()//报错,因为上面声明了是联合类型
    //getSmallPet只能是Fish或者Bird
    //所以只能调用它们共有的方法

    类型保护

    上述例子中我们如何判断是哪个类型呢

    interface Bird {
      fly()
    
      layEggs()
    }
    
    interface Fish {
      swim()
    
      layEggs()
    }
    
    function getSmallPet(): Fish | Bird {
      return //...
    }
    
    let pet = getSmallPet()
    
    if (isFish(pet)){
      pet.swim()
    } else {
      pet.fly()
    }
    //类型谓词的类型保护机制
    function isFish(pet: Fish | Bird): pet is Fish {
     return (pet as Fish).swim !== undefined 
    }
    function isNumber(x: any): x is number {
      return typeof x === 'number'
    }
    
    function isString(x: any): x is string {
      return typeof x === 'string'
    }
    
    function padLeft(value: string, padding: string | number){
      if (isNumber(padding)) {
        return Array(padding + 1).join('') + value
      }
      if (isString(padding)) {
        return padding + value
      }
      throw new Error(`Expected string or number, got ${padding}`)
    }

    typeof的类型保护机制

    //typeof对基础类型提供类型保护,可以直接推断出值的类型,而不必像上例那样写
    //一般 === 和 !==提供保护
    //其他的可以用谓词保护
    function padLeft(value: string, padding: string | number){
      if (typeof padding === 'number') {
        return Array(padding + 1).join('') + value
      }
      if (typeof padding === 'string') {
        return padding + value
      }
      throw new Error(`Expected string or number, got ${padding}`)

    instanceof类型保护

    class Bird {
      fly() {
        console.log('bird fly')
      }
    
      layEggs(){
        console.log('bird lay eggs')
      }
    }
    
    class Fish {
      swim(){
        console.log('fish swimming')
      }
    
      layEggs(){
        console.log('fish lay eggs')
      }
    }
    
    function getRandomPet(): Fish | Bird {
      return Math.random() > 0.5 ? new Bird() : new Fish()
    }
    
    let pet = getRandomPet()
    
    if (pet instanceof Bird) {
      pet.fly()
    }
    
    if (pet instanceof Fish) {
      pet.swim()
    }

     null和undefined

    回顾之前的代码

    let s = null
    s = null
    let sn: string | null = 'bar'
    sn = null
    
    sn = undefined
    //这段代码在编译时是不会出错的
    //加上参数 --strictNullChecks会编译出错
    function f(x: number, y?: number){
      return x + (y || 0)
    }
    
    f(1,2)
    f(1)
    f(1,undefined)
    
    //f(1,null)报错
    // 'null' is not assignable to parameter of type 'number | undefined'.

    在类中也是一样

    class C {
      a:number
      b?:number//相当于联合类型number | undefined
    }
    
    let c = new C()
    c.a = 12
    c.a = undefined //报错,a为number
    c.b = 13
    c.b = undefined
    c.b = null //报错

    null的类型保护和类型断言

    function broken(name: string | null ): string {
      function postfix(epither: string) {
        return name!.charAt(0) + '. the' + epither
      } 
      name = name || 'Bob'
      return postfix(name)
    }
    //上述函数在编译时出错 --strictNullChecks
    //ts编译器不知道name是否为null
    //我们可以用类型断言方式给name加上!表示name不为null

    高级类型之字符串字面量类型

    type Easing = 'ease-in' | 'ease-out' | 'ease-in-out'
    
    class UIElement {
      animate(dx: number, dy: number,easing: Easing) {
        if (easing === 'ease-in') {
          //...
        } else if (easing === 'ease-out') {
    
        }else if (easing === 'ease-in-out') {
    
        }else {
    
        }
      }
    }
    
    let button = new UIElement()
    button.animate(0, 0, 'ease-in')
    //button.animate(0, 0, null)//编译时报错
    //Argument of type 'null' is not assignable to parameter of type 'Easing'.

    2019-05-30  09:53:16

    工欲善其事,必先利其器
  • 相关阅读:
    JavaScript学习(五)
    浏览器输入地址到返回页面
    session cookie
    springboot 运行jar包
    mysql:The user specified as a definer ('root'@'%') does not exist
    easyUI
    json
    json fastjson
    springboot:because it is a JDK dynamic proxy that implements:
    git 提示错误:(non-fast-forward)
  • 原文地址:https://www.cnblogs.com/ccbest/p/10945225.html
Copyright © 2011-2022 走看看