Skip to content

泛型

泛型(Generics),可以理解为类型参数。它的核心思想是,在定义函数、接口、类和别名时以参数的形式表示类型,在调用的时候传入具体的类型。

如何使用泛型?

语法:在名称后面使用尖括号 <T> 来声明泛型类型参数,(T 是 Type 的含义,也可以用 UK 等)

在函数中使用

在函数名称后定义

typescript
// 将传入的参数返回
function identity<T>(arg: T): T {
  return arg;
}

// 两种调用方式:
// 1. 显式指定类型
const output1  = identity<string>('hello')

// 2. 类型推断(推荐)
const output2 = identity("hello"); // TS 自动推断 T 为 string

在接口、类和别名的使用也一样,在名称后面定义:

typescript
// 接口
interface Box<T> {
  value: T
}

const numberBox: Box<number> = { value: 42 };

// 类
class Container<T> {
  private data: T;

  constructor(value: T) {
    this.data = value;
  }

  getData(): T {
    return this.data;
  }
}

const numContainer = new Container<number>(100);
const strContainer = new Container("hello");

泛型类

泛型不能用于静态成员(因为静态成员属于类本身,而不是实例,而泛型是在实例化时确定的)。

泛型约束

有时我们希望泛型满足某些条件,比如必须有某个属性,这个时候会出现这样一个问题:

typescript
function getLength<T>(o: T): T {
  return o.length // ❌ 无法确定o是否有length属性
}

这个时候,我们可以使用 extends 对泛型进行约束。

typescript
interface LengthProps {
	length: number
}

function getLength<T extends LengthProps>(o: T): T {
  return o.length // ✅ 可以确保o有length属性,并且有ts提示
}

const length1 = getLength("hello"); // ✅ string类型有length属性
const length2 = getLength([1]); // ✅ array类型有length属性
const length3 = getLength(1); // ❌ number类型没有length属性