美文网首页
TypeScript(七):泛型

TypeScript(七):泛型

作者: 林ze宏 | 来源:发表于2021-05-08 13:45 被阅读0次

    1 泛型的基础

    泛型是指在定义函数或者接口的时候,不指定类型,只在使用的时候,才指定类型的一种特征,相当于一个占位符。

    • 实例一,简单例子
    // <T> 是指第一个参数的泛型
    function echo<T>(arg: T): T {
      return arg
    }
    
    const result1: boolean = echo(true)
    
    const result2: number = echo(111)
    
    • 实例二,两个参数互换位置
    function swap<T, U>(tuple: [T, U]): [U, T] {
      return [tuple[1], tuple[0]]
    }
    const result3 = swap(['string', 123])
    
    

    2 泛型约束

    当函数使用泛型时,想要参数拥有 length 属性,如果是直接使用泛型限制,如下例子,则会报错:

    function echoWithArr1<T>(arg: T): T {
      console.log(arg.length) // Property 'length' does not exist on type 'T'
      return arg
    }
    
    

    这时候,需要对参数进行约束,或者限定,解决方案一,如下:参数使用对象,因为对象就有了 length 属性,如下:

    // arg: T[]  =>  arg: Array<T>
    function echoWithArr<T>(arg: T[]): T[] {
      console.log(arg.length)
      return arg
    }
    const arrs = echoWithArr([1, 2, 3])
    
    

    这种方法不是太好,因为如果想要传入 string,或者对象就会报错;

    解决方案二,使用接口约束泛型:关键字 extends

    interface IWithLength {
      length: number
    }
    
    function echoWithLength<T extends IWithLength>(arg: T): T {
      console.log(arg.length)
      return arg
    }
    
    const str = echoWithLength('str')
    const obj = echoWithLength({ length: 10, width: 10})
    const arr2 = echoWithLength([1, 2, 3])
    

    3 泛型,类和接口

    • 类使用泛型
    class Queue<T> {
      private data = [];
      push(item: T) {
        return this.data.push(item)
      }
      pop(): T {
        return this.data.shift()
      }
    }
    
    const queue = new Queue<number>()
    queue.push(1) // 添加数字,拥有数字的方法
    console.log(queue.pop().toFixed())
    
    
    const queue2 = new Queue<string>()
    queue2.push('str') // 添加字符串,拥有字符串的方法
    console.log(queue2.pop().length)
    
    • 接口使用泛型
    interface KeyPair<T, U> {
      key: T;
      value: U;
    }
    let kp1: KeyPair<number, string> = { key: 123, value: "str" }
    let kp2: KeyPair<string, number> = { key: 'test', value: 123 }
    
    • 对象使用接口泛型
    let arr: number[] = [1, 2, 3]
    
    等价于
    
    let arrTwo: Array<number> = [1, 2, 3] // Array 是接口,封装了很多方法
    
    • 接口来描述函数的类型
    interface IPlus<T> {
      (a: T, b: T) : T
    }
    
    function plus(a: number, b: number): number {
      return a + b;
    }
    const a: IPlus<number> = plus // 用接口来描 a 类型,使它等于 plus 函数类型
    
    
    
    function connect(a: string, b: string): string {
      return a + b
    }
    const b: IPlus<string> = connect // 用接口来描 b 类型,使它等于 connect 函数类型
    

    4 相关示例

    // 最简单类泛型
    class DateList<T> {
      constructor(private data: T[]) {}
      getItem(index: number): T {
        return this.data[index];
      }
    }
    new DateList<string>(['1']);
    new DateList(['1']);
    
    
    // 给泛型新增限制,必须有 name 属性
    interface Item {
      name: string;
    }
    class DateList<T extends Item> {
      constructor(private data: T[]) {}
      getItem(index: number): string {
        return this.data[index].name;
      }
    }
    new DateList<Item>([{ name: 'xiaoming' }]);
    new DateList([{ name: 'xiaoming' }]);
    
    // 泛型必须是 number 或者 string
    class DateList<T extends string | number> {
      constructor(private data: T[]) {}
      getItem(index: number): T {
        return this.data[index];
      }
    }
    new DateList<string>(['1']);
    new DateList(['1']);
    new DateList<number>([1]);
    new DateList([1]);
    
    // 函数使用泛型限制
    const func: <T>(params: T) => T = <T>(params: T) => {
      return params;
    }
    

    相关文章

      网友评论

          本文标题:TypeScript(七):泛型

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