TS:泛型的使用方法

前端 同时被 3 个专栏收录
63 篇文章 0 订阅
12 篇文章 0 订阅
60 篇文章 0 订阅

TS:泛型

1. 前言

  • 有时候,我们想让一个函数的参数和返回类型是相同的,就可以使用类型变量

  • 类型变量是一种特殊的变量,用于表示类型而不是值。

    function identity<T>(arg : T) : T{
        return arg;
    }
    
  • 定义了泛型函数后,可以用两种方法使用。

  • 一种是传入所有的参数,包括类型参数:

    let out = identity<string>("yivi");
    
  • 另一种是使用类型推论——即编译器会自动推断类型:

    let out = identity("yivi");
    
  • 类型推论帮助我们保持代码精简和高可读性。

2. 泛型变量

  • 来看看一个例子:

    function foo<T>(arg : T): T{
        console.log(arg.length);	// error,arg的类型为T,无明确指示方法,因此报错。
        return arg;
    }
    
  • 当我们想操作T类型的数组时,.length的属性是存在的,因此不会报错:

    function foo<T>(args : T[]):T[]{
        console.log(args.length);
        return args;
    }
    
    // or
    
    function foo<T>(args : Array<T>) : Array<T>{
        console.log(args.length);
        return args;
    }
    

3. 泛型类型

  • 我们可以使用不同的泛型参数名,只要保证数量和使用方式一致即可;

  • 也可以使用带有调用签名的对象字面量来定义泛型函数;

    function identity<T>(arg : T) : T{
        return arg;
    }
    
    let myIdentity : <U>(arg : U) => U = identity;
    
    // or 
    
    let myIdentity : {<T>(arg : T):T} = identity;
    
  • 将上面的对象字面量拿出来写成一个接口:

    interface IdentityInterface{
        <T>(arg : T) : T;
    }
    
    function identity<T> (arg : T) : T{
        return arg;
    }
    
    let myidentity : IdentityInterface = identity;
    
  • 也可以将泛型参数当作整个接口的一个参数,这样就保证我们知道使用的是哪个泛型类型:

    interface IdentityInterface<T>{
        (arg : T) : T;
    }
    
    function identity<T> (arg : T) : T{
        return arg;
    }
    
    let myidentity : IdentityInterface<string> = identity;
    
  • 泛型类与泛型接口差不多,都使用<>来进行约束:

    class Foo<T>{
        state : T;
        add : (x : T, y : T) => T;
    }
    
    let myfoo = new Foo<number>();
    myfoo.state = 1;
    myfoo.add = (x,y)=>{
        return x + y;
    }
    

4. 泛型约束

  • 上面的例子中,我们提到了.length这个属性如果用在泛型上,就会报错;

  • 因此,我们只需要实现一个接口,让该泛型有这个属性,就可以防止编译器报错了;

    interface Length{
        length : number;
    }
    
    function identity<T extends Length>(arg : T) : T{
        console.log(arg.length);
        return arg;
    }
    
  • 虽然编译器不会报错了,但如果使用了没有该属性的类型,也是同样会报错;

  • 所以我们需要传入符合约束的值,且包含必须的属性;

    identity({length : 10,value : 100});
    

5. 在泛型中使用 类 类型

  • 在typescript中使用泛型创建工厂函数时,需要引用构造函数的类类型。

    function create<T> (c : {new() : T}) : T{
        return new c();
    }
    
    class Foo{
        name : string;
    }
    
    let a : Foo = create(Foo);
    a.name = 'yivi'
    console.log(a.name)
    
  • 1
    点赞
  • 0
    评论
  • 4
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

Yivisir

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值