You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript函数中如何使用泛型并获取泛型T的类型?

嘿,刚好对TypeScript泛型这块熟得很,我来给你一步步讲清楚函数里怎么用泛型,以及怎么获取泛型参数T的具体类型!

一、函数中使用泛型的基础玩法

泛型的核心是让函数能适配多种类型,同时保留类型检查,不用写一堆any。

1. 最基础的泛型函数定义

在函数名后面加<T>(T是约定俗成的泛型参数名,你换成U、V也没问题),然后在参数、返回值里用T指代这个类型:

// 一个返回传入值的通用函数
function identity<T>(arg: T): T {
  return arg;
}

使用的时候有两种方式:

  • 显式指定类型:const numResult = identity<number>(123);
  • 让TypeScript自动推断:const strResult = identity("hello");(TS会自动把T推断成string)

2. 带约束的泛型函数

如果想限制T的范围,比如必须包含某个属性,可以用extends:

interface HasId {
  id: number;
}

// T必须是HasId的子类/实现类
function getEntityById<T extends HasId>(entities: T[], id: number): T | undefined {
  return entities.find(item => item.id === id);
}

// 传入符合HasId的数组,TS会自动推断T的具体类型
const users = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
const foundUser = getEntityById(users, 1); // foundUser的类型是{ id: number; name: string; } | undefined
二、获取泛型参数T的具体类型

这里要分编译时(类型层面)和运行时两种场景,因为TypeScript的类型会在编译成JS后被擦除,两者的处理方式完全不同。

1. 编译时提取T的类型

在类型层面,TypeScript提供了很多工具类型,或者你可以自己写类型工具来提取T:

从泛型函数中提取T

比如想拿到上面identity函数的参数/返回值类型(也就是T):

// 获取identity函数的第一个参数类型
type IdentityArgType = Parameters<typeof identity>[0];
// 获取identity函数的返回值类型
type IdentityReturnType = ReturnType<typeof identity>;

// 如果我们显式调用identity<number>(123),那这两个类型都会是number

自定义类型工具提取泛型参数

如果有一个泛型接口/类型,想把它的泛型参数抽出来,可以用infer关键字:

// 定义一个工具类型,用来提取泛型类型的参数
type ExtractGenericParam<T> = T extends GenericContainer<infer U> ? U : never;

// 一个泛型容器接口
interface GenericContainer<T> {
  value: T;
}

// 提取GenericContainer<string>的泛型参数
type ExtractedType = ExtractGenericParam<GenericContainer<string>>; // ExtractedType就是string

2. 运行时获取T的类型

因为编译时类型擦除,运行时根本没有T这个概念,所以我们得用JavaScript本身的手段来判断:

判断基本类型

用typeof操作符:

function getRuntimeType<T>(arg: T): string {
  switch (typeof arg) {
    case "string":
      return "string";
    case "number":
      return "number";
    case "boolean":
      return "boolean";
    // 其他基本类型...
    default:
      return "object/function/unknown";
  }
}

判断引用类型

用instanceof操作符,适用于类实例:

class Cat { meow() {} }
class Dog { woof() {} }

function checkAnimalType<T>(animal: T): string {
  if (animal instanceof Cat) {
    return "Cat";
  } else if (animal instanceof Dog) {
    return "Dog";
  }
  return "Unknown Animal";
}

手动传递类型标记

如果需要更精确的类型信息(比如区分不同的对象类型),可以在调用函数时额外传一个类型标识:

function processItem<T>(item: T, type: "user" | "product"): void {
  if (type === "user") {
    // 这里可以安全地把item当作User类型处理
    console.log("Processing user:", (item as User).name);
  } else {
    console.log("Processing product:", (item as Product).sku);
  }
}

processItem({ id: 1, name: "Alice" }, "user");

总的来说,泛型让你的函数更灵活复用,编译时靠TypeScript的类型工具就能轻松提取T的类型,运行时则要借助JS的原生判断或者手动传递类型信息来实现。

内容的提问来源于stack exchange,提问作者kirno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:43:37