泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

初识泛型

泛型只在编译阶段有效。主要使用方式:泛型类,泛型接口,泛型方法。

首先来看一个例子,创建10个汤姆:

typescript 泛型断言 typescript中的泛型_css


前端优选

function createToms(length:number,name: any): Array<any>{
    let result = [];
    for(let i=0;i<length;i++){
        result[i] = name;
    }
    return result;
}

console.log(createToms(10,'tom'));     //['tom', 'tom', 'tom','tom', 'tom', 'tom','tom', 'tom', 'tom','tom']

该方法创建一个指定长度的数组,代码编译的时候不会报错,但是有一个显而易见的缺点就是:它并没有规定返回值类型。Array允许填充任意类型的值,但是我们期望数组的每一项都是name的类型。

泛型登场

function createToms<T>(length:number,name: T): Array<T>{
    let result = [];
    for(let i=0;i<length;i++){
        result[i] = name;
    }
    return result;
}

console.log(createToms<string>(10,'tom'));     //['tom', 'tom', 'tom','tom', 'tom', 'tom','tom', 'tom', 'tom','tom']

函数名后面添加了,T可以用来代替任意输入的类型,在后面输入的T和输出的Array即可使用了。

这里T代表Type,定义泛型时一般将第一个类型变量的名称用作泛型代表。实际上T可以用任何有效字母来代替,一般情况下,K(Key)表示键类型;V(Value)表示值类型;E(Element)表示元素类型。

多个泛型

还是同样的方法,但是我有可能创建的不是汤姆了:

typescript 泛型断言 typescript中的泛型_js_02


前端优选

function createToms<T,U>(length: T,name: U):Array<T>{
    let result = [];
    for(let i=0;i < Number(length);i++){
        result[i] = name;
    }
    return result;
}

console.log(createToms<number,string>(10,'tom'));     //['tom', 'tom', 'tom','tom', 'tom', 'tom','tom', 'tom', 'tom','tom']
console.log(createToms<number,number>(10,86));     //[86, 86, 86, 86,86, 86, 86, 86,86, 86]

在调用的时候指定具体类型为tom或者86,当然,如果不指定也可以根据参数推定出来。

多个类型参数

定义泛型的时候,可以一次定义多个类型参数

function createTom<T,U>(tuple: [T,U]): [T,U]{
    return [tuple[0],tuple[1]];
}

console.log(createTom([18,'Tom']));         //[ 18, 'Tom' ]
function createTom<T,U>(tuple: [T,U]): [U,T]{
    return [tuple[1],tuple[0]];
}

console.log(createTom([18,'Tom']));         //[ 'Tom', 18 ]

上例中,在返回值位置取值tuple值是相反的,这样写的目的希望您更能容易理解元组(元组:合并了不同类型的对象)取值方式。同时,上例也表现了定义泛型时,一次定义多个类型参数。

泛型约束

泛型约束的目的是保证要使用的属性或方法存在:

interface lengthType {
    len: number;
}

function createToms<T extends lengthType,U>(length: T,name: U):Array<T>{
    let result = [];
    for(let i=0;i < length.len;i++){        //保证运算符<应用于Number类型参数
        result[i] = name;
    }
    return result;
}
let res = createToms<lengthType,string>({len:3},'tom');     //[ 'tom', 'tom', 'tom' ]

这里限制参数类型必须满足lengthType接口,因此T处应放置lengthType

有了泛型之后,一个函数或容器类能处理的类型一下子扩到了无限大,似乎有点失控的感觉。因此又产生了多个类型参数之间可以互相约束的概念。

function copyCousin<T extends U,U>(target: T,source: U): T{
    for(let k in source){
        target[k] = (<T>source)[k];
    }
    return target;
}

let jerry = {a:1,b:2,c:3,d:4};

console.log(copyCousin(jerry,{b:20,c:30}))      //{ a: 1, b: 20, c: 30, d: 4 }

使用了两个类型参数,其中要求T继承自U,这样就保证了U上不会出现T没有的字段。

杰瑞继承自表哥的衣服属性,即可获得相应的能力去震慑汤姆。

typescript 泛型断言 typescript中的泛型_js_03


前端优选

泛型接口

上例的createToms方法中通过接口限制了参数类型,当然也可以通过泛型来直接限制接口:

interface createTom{
    <T>(length: number,name: T) : Array<T>
}

let Tom: createTom;

Tom = function<T>(length:number,name: T): Array<T>{
    let result: T[] = [];
    for(let i=0;i<length;i++){
        result[i] = name;
    }
    return result;
}

console.log(Tom(3,'tom'));      //[ 'tom', 'tom', 'tom' ]

typescript 泛型断言 typescript中的泛型_java_04


前端优选

泛型类

与泛型接口类似,泛型还可以用于定义类中:

class createTom<T>{
    catching:(x:T,y:T) => T;
}

let tom = new createTom<string>();
tom.catching = (x,y) => {return x + y}

console.log(tom.catching('Tom',' is catching Jerry.'));     //Tom is catching Jerry.

简单来说,就是可以用来限制方法参数类型。

typescript 泛型断言 typescript中的泛型_css_05


前端优选 本文简单介绍了TypeScript泛型的基本用法,泛型在编码过程中是非常重要的一个环节,希望本文能帮助到大家,欢迎大家继续关注后续内容哦~