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

    工欲善其事,必先利其器
  • 相关阅读:
    ubuntu安装jdk的两种方法
    LeetCode 606. Construct String from Binary Tree (建立一个二叉树的string)
    LeetCode 617. Merge Two Binary Tree (合并两个二叉树)
    LeetCode 476. Number Complement (数的补数)
    LeetCode 575. Distribute Candies (发糖果)
    LeetCode 461. Hamming Distance (汉明距离)
    LeetCode 405. Convert a Number to Hexadecimal (把一个数转化为16进制)
    LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)
    LeetCode 371. Sum of Two Integers (两数之和)
    LeetCode 342. Power of Four (4的次方)
  • 原文地址:https://www.cnblogs.com/ccbest/p/10945225.html
Copyright © 2011-2022 走看看