Hello Typescript(08)-- 泛型

本文详细讲解了如何在 TypeScript 中使用泛型,从基本的函数定义到泛型接口、类的使用,以及泛型约束的实践,提升代码的灵活性和扩展性。了解泛型如何简化重用和类型管理,是提高TypeScript编程效率的关键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:实现一个打印函数

function log(value: string): string {
  console.log(value);
  return value;
}
  • 需求+1:函数也要可以接受字符串数组

    这里我们可能想到了用函数重载。

    function log(value: string): string;
    function log(value: string[]): string[];
    function log(value: any): any {
      console.log(value);
      return value;
    }
    
  • 需求+2:这个函数会返回任何传入它的值,且类型保持一致。
    我们可以用 any 类型,实现传入任何类型。但会丢失部分信息(类型之间的约束关系),忽略了 输入参数的类型和返回值的类型必须是一致的

    function log(value: any) {
      console.log(value);
      return value;
    }
    

    此时,我们用 类型变量,它是一种特殊的变量,只用于表示类型而不是值。

    function log<T>(value: T): T {
      console.log(value);
      return value;
    }
    

    变量 T 捕获传入参数的类型,之后我们就可以使用这个 T 类型,再将 T 作为返回值类型。
    此时,这个版本的 log 函数叫做 泛型

什么是泛型

不预先确定的数据类型,具体类型在使用时才可以确定。

  • 两种调用方式

    • 指明类型

      log<string[]>(["a", "b", "c"]);
      
    • 类型推断

      log(["a", "b", "c"]);
      
  • 泛型类型

    我们不仅可以用泛型定义函数,还可以定义函数类型
    可以将泛型类型看成只定义类型的传参,帮助理解。

    function log<T>(value: T): T {
      console.log(value);
      return value;
    }
    
    type MyLog = <T>(value: T) => T;
    let myLog: MyLog = log;
    
    // 还可以使用不同的泛型参数名,只要数量和使用方式能对应上。
    type ULog = <U>(value: U) => U;
    
    // 还可以使用带有调用签名的对象字面量来定义泛型函数:
    type OLog = { <T>(value: T): T };
    
  • 泛型接口

    interface MyLog {
      // 泛型仅仅约束函数
      <T>(value: T): T;
    }
    
    // 泛型约束了整个接口,实现时必须指定类型,或在接口定义是指定默认类型
    interface MyLog<T = string> {
      (value: T): T;
    }
    
    let ilog: ILog<number> = log;
    
  • 泛型类

    泛型类指的是实例部分的类型,所以类的 静态属性 不能使用这个泛型类型。

    class Gen<T> {
      constructor() {}
      run(value: T): T {
        console.log(value);
        return value;
      }
    }
    let gen1 = new Gen<number>();
    gen1.run(1);
    gen1.run("1"); // error!
    let gen2 = new Gen(); // 默认 any
    gen2.run(1);
    gen2.run("1");
    
  • 泛型约束

    我们定义一个接口来描述约束条件。
    使用这个接口和 extends 关键字来实现约束:

    interface Length {
      length: number;
    }
    function log<T extends Length>(value: T) {
      console.log(value.length);
      return value;
    }
    
    log("1");
    log([1, 2, 3]);
    log({ length: 1 });
    log(2); // error!
    

泛型有什么好处呢?

  • 函数和类可以轻松支持多种类型,增强程序的扩展性。
  • 不必写多条函数重载,冗长的联合类型声明,增加代码可读性。
  • 灵活控制类型之间的约束。

TypeScript 入门系列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值