美文网首页
typescript---泛型

typescript---泛型

作者: 成熟稳重的李先生 | 来源:发表于2020-02-12 21:51 被阅读0次

    泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
    泛型T作用域只限于函数内部使用

    1. 泛型函数
    • 首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值
    function createArray(length: number, value: any): Array<any> {
        let result: any = [];
        for(let i=0;i<length;i++){
            result[i] = value;
        }
        return result;
    }
    let result = createArray(3,'x');
    console.log(result);
    

    使用泛型后

    function createArray<T>(length: number, value: T): Array<T> {  //这样,就约束了返回数组的类型
            let result: T[] = [];
            for(let i=0;i<length;i++){
                result[i] = value;
            }
            return result;
    }
    let arr = createArray<number>(3, 5);  
    let arr = createArray<number>(3, "a");
    
    1. 泛型类
    • 类数组(Array-like Object)不是数组类型,比如 arguments
        class Person<T> {  // T的作用域是整个类
            private list: T[] = [];
            add(value: T) {
                this.list.push(value);
            }
            getMax() {
                let result: T = this.list[0];
                for(let i =1;i<this.list.length;i++){
                    if(this.list[i] > result){
                        result = this.list[i];
                    }
                }
                return result;
            }
        }
    

    3.泛型接口

    • 泛型接口可以用来约束函数
    interface Caculate {
      <T>(a: T, b: T): T
    }
    const add: Caculate = function <T>(a: T, b: T): T{
        return a
    }
    add<number>(3,5)
    add<number>(3,"5") //报错,此处T是number,“5”是字符串
    
    1. 多个类型参数
    function swap<A, B>(touple: [A, B]): [B, A] { //touple是元组
        return [touple[1], touple[0]]
    }
    let swapped = swap<string,number>(['a',1]);
    console.log(swapped);
    console.log(swapped[0].toFixed(2));
    console.log(swapped[1].length);
    
    1. 默认泛型类型
    function createArray3<T=number>(length: number, value: T): Array<T> {
      let result: T[] = [];
      for (let i = 0; i < length; i++) {
        result[i] = value;
      }
      return result;
    }
    let result2 = createArray3(3,3);
    let result3 = createArray3<string>(3,'3');
    
    1. 泛型约束
    • 在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。
    function logger<T>(val: T) {
        console.log(val.length); //直接访问会报错,因为T类型未知,不一定有length属性
    }
    interface LengthWise {
        length: number
    }
    
    //可以让泛型继承一个接口
    function logger2<T extends LengthWise>(val: T) {
        console.log(val.length)
    }
    logger2('lc');  // 2
    logger2({length: 5});  //5
    logger2(1); //报错,1或者new Number(1)都没有length属性
    
    1. 泛型接口
    • 定义接口的时候也可以指定泛型
    interface Cart<T>{
      list:T[]
    }
    let cart:Cart<{name:string,price:number}> = {
      list:[{name:'zhufeng',price:10}]
    }
    console.log(cart.list[0].name,cart.list[0].price);
    
    1. 泛型类型别名
    • 泛型类型别名可以表达更复杂的类型
    type Cart<T> = {list:T[]} | T[];  //联合类型
    let c1:Cart<string> = {list:['1']};
    let c2:Cart<number> = [1];
    
    1. 泛型接口 vs 泛型类型别名
    • 接口创建了一个新的名字,它可以在其他任意地方被调用。而类型别名并不创建新的名字,例如报错信息就不会使用别名
    • 类型别名不能被 extends和 implements,这时我们应该尽量使用接口代替类型别名
    • 当我们需要使用联合类型或者元组类型的时候,类型别名会更合适

    相关文章

      网友评论

          本文标题:typescript---泛型

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