美文网首页
TypeScript泛型(generic)

TypeScript泛型(generic)

作者: 不思量q | 来源:发表于2019-11-21 22:55 被阅读0次
    /**
     * generic泛型,给予了开发者创造灵活、可重用代码的能力
     * 场景1,假设有个函数A,接受number类型的参数,并返回number类型的值
     * 那如果同样的函数B,参数和返回值类型要改变成string,那非得写两个函数么,或者写成any类型?
     * 也就是说在静态编写的时候并不确定传入的参数类型,只有运行时传入参数后才可确定
     * 这里可以看做需要一个变量,变量代表了传入的类型,然后再返回这个变量,它为一种特殊变量,只用于表示类型而不表示值,即为泛型
     */
    function getType(para: string): string {
      return para
    }
    
    function returnItem<T>(para: T): T {
      return para
    }
    // 编译成JS文件后这俩函数是一样的
    
    // 多个参数类型
    function swap<T, U>(tuple: [T, U]): [U, T] {
      return [tuple[1], tuple[0]]
    }
    console.log(swap([2, '2oops'])) // ['2oops', 2]
    
    // 假设函数接收一个数组,要求打印数组长度,并返回数组
    function getLength<T>(arg: Array<T>) {
    
      console.log((arg as Array<any>).length)
      return arg
    }
    getLength([1,2,3])
    
    // 泛型接口
    interface ReturnItemFn<T> {
      (para: T): T
    }
    const Fun1: ReturnItemFn<string> = params => params + '2oops'
    console.log(Fun1('hello '))
    
    // 泛型类
    class Stack {
      private arr: number[] = []
    
      public push(item: number) {
        this.arr.push(item)
      }
    
      public pop() {
        this.arr.pop()
      }
    }
    
    class GenericStack<T> { // 泛型在类中使用
      private arr: T[] = []
    
      public push(item: T) { // 泛型在类的成员函数中使用
        this.arr.push(item)
      }
    
      public pop() {
        this.arr.pop()
      }
    }
    
    // 泛型约束 <T extends types>
    type types = number | string
    
    class TypeStack<T extends types> {
      private arr: T[] = []
    
      public push(item: T) {
        this.arr.push(item)
      }
    
      public pop() {
        this.arr.pop()
      }
    }
    
    const stack1 = new TypeStack<number>()
    // const stack2 = new TypeStack<boolean>()
    
    // 泛型约束和索引类型
    // 假设设计一个函数接收一个对象和对象的属性作为参数,通过这两个参数返回这两个值
    // 直接JS实现可能会写成下面这样,但这是不严谨的
    // function getValue(obj, key) {
    //   return obj[key]
    // }
    // 然后用TS写成这样?obj为空的场景?
    // function getValue(obj: object, key: string) {
    //   return obj[key] // error
    // }
    
    // 正确写法
    function getValue2<T extends object, U extends keyof T>(obj: T, key: U) {
      console.log(obj[key])
      return obj[key]
    }
    
    const obj1 = {
      name: '2oops',
      age: 20
    }
    getValue2(obj1, "name") // '2oops'
    
    // 使用多重类型进行泛型约束
    // 假设泛型被需要被以下两个接口约束
    interface first {
      doSomething(): number
    }
    interface second {
      doSomethingElse(): string
    }
    
    // 或许我们会这样使用
    // class interfaceGeneric<T extends first, second> {
    //   private genericProperty: T
    
    //   useT() {
    //     this.genericProperty.doSomething()
    //     // this.genericProperty.doSomethingElse() //报错不存在该泛型
    //   }
    // }
    
    // 这时可以将俩接口作为超接口
    interface ChildInterface extends first, second {
    
    }
    class interfaceGeneric<T extends ChildInterface> {
      private genericProperty: T
      // 如果直接这样写会报错,这时需要在tsfonfig.json设置下`"strictPropertyInitialization": false`
      // 报错参考https://stackoverflow.com/questions/49699067/property-has-no-initializer-and-is-not-definitely-assigned-in-the-construc
    
      useT() {
        this.genericProperty.doSomething()
        this.genericProperty.doSomethingElse()
      }
    }
    
    // 泛型和new
    // 声明一个泛型其拥有构造函数
    function factory<T>(type: {new(): T}): T {
      return new type()
    }
    

    相关文章

      网友评论

          本文标题:TypeScript泛型(generic)

          本文链接:https://www.haomeiwen.com/subject/yrntwctx.html