typescript教程:函数的返回值泛型

介绍

在 TypeScript 中,函数返回值泛型的核心作用是:让函数的返回值类型,和入参类型/指定的类型保持一致,实现类型安全的复用,避免写重复代码。

理解

函数的返回值类型,由调用者自己决定,就叫返回值泛型

简单说:

  • 普通函数:返回值类型写死,一辈子只能返回一种类型

  • 返回值泛型函数:函数代码不改,想要什么类型,就返回什么类型

基础用法

自动推导返回值

泛型用 <T> 定义,TS 会自动根据入参推导返回值类型。

// 定义泛型函数:T 代表任意类型
function identity<T>(arg: T): T {
  return arg; // 返回值类型 = 入参类型
}

// 使用
let str = identity("hello"); // str: string
let num = identity(123);     // num: number
let bool = identity(true);   // bool: boolean

✅ 优势:

  • 不用为 string/number/boolean 分别写函数
  • 返回值类型完全精准,TS 会自动提示对应类型的属性/方法

手动指定返回值泛型

有时候 TS 无法自动推导,你可以手动传入泛型类型,强制规定返回值:

function getData<T>(): T {
  // 模拟接口返回
  return {} as T;
}

// 手动指定:返回值一定是 User 类型
interface User {
  name: string;
  age: number;
}

const user = getData<User>(); 
// user: User → TS 会自动提示 name、age

例子

  • 一个全局 Map 存数据

  • 存数据函数:没有泛型,普通参数

  • 取数据函数:只有返回值是泛型

1、定义全局缓存仓库

// 全局缓存仓库,统一存页面全局数据
const globalCache = new Map<string, unknown>()

2、存数据函数

// 存数据:固定 key字符串,value任意值,不需要泛型
function setCache(key: string, value: unknown): void {
  globalCache.set(key, value)
  console.log("保存成功:", key)
}

3. 无泛型 纯普通获取(原始写法,不推荐)

// 无泛型,返回固定 unknown
function getCache(key: string): unknown {
  return globalCache.get(key)
}
使用
// 拿到的变量全是 unknown 类型
const user = getCache("userInfo")
const token = getCache("token")

// ❌ 直接使用全部报错
// user.name    // 报错:类型“unknown”上不存在属性“name”
// token.length // 报错:类型“unknown”上不存在属性“length”
强行使用只能手动类型断言
// 每次取值都要手动写断言,重复、繁琐
const user = getCache("userInfo") as { name: string; age: number }
const token = getCache("token") as string

user.name
token.length
无泛型缺点
  1. 默认返回 unknown,无任何代码提示
  2. 访问属性/方法直接红线报错
  3. 每一次取值都要手动 as 类型,代码冗余
  4. 类型写错不会及时校验,容易埋线上bug

4. 返回值泛型(推荐)

// 入参 key 固定 string,无泛型
// 只有返回值 T 为泛型,由调用方传入类型
function getCache<T>(key: string): T {
  return globalCache.get(key) as T
}
使用
// 取值时 显式传入泛型类型,直接锁定返回值类型
const user = getCache<{ name: string; age: number }>("userInfo")
const token = getCache<string>("token")

// ✅ 完美智能提示
user.name
user.age

token.length
token.trim()
也可以抽离接口,更优雅(企业常用)
interface UserInfo {
  name: string
  age: number
}

// 语义更清晰,复用类型
const user = getCache<UserInfo>("userInfo")

5、企业真实使用场景

// 1、先存数据(普通存储,不用管类型)
setCache("userInfo", { name: "李四", age: 20 })
setCache("token", "abc123456")

// 2、取数据【返回值泛型生效】
// 取用户,自动识别用户对象类型
const user = getCache<{ name: string; age: number }>("userInfo")
user.name // ✅ 有提示,乱写报错

// 取令牌,自动识别字符串类型
const token = getCache<string>("token")
token.length // ✅ 字符串方法提示

两种写法核心对比

对比项 无泛型(unknown) 返回值泛型<T>
返回类型 固定 unknown 调用方自定义 T
代码提示 无 完整属性/方法提示
类型安全 差,全靠手动断言 强类型约束
重复代码 每次取值必写 as xxx 一次指定类型,直接用
错误校验 类型错误不易发现 写错类型直接TS红线

返回值泛型 核心好处

  1. 存的时候随便存
    setCache 保持简单,unknown 兼容所有数据,不用复杂泛型。

  2. 取的时候精准约束
    只有读取时才声明类型,读写分离,符合缓存业务逻辑。

  3. 杜绝隐式类型错误

    // 泛型约束下,写错类型直接报错
    const token = getCache<number>("token") 
    // 明知是字符串,写成 number,编码阶段就预警
    
  4. 多人协作友好
    别人看代码一眼就知道:这个 key 对应什么数据结构。

一句话总结

返回值泛型的作用:函数逻辑写死不变,参数正常干活不变,只有返回值类型,随业务自己定义。

不写死类型、不用 any、类型不丢失、一个函数通用所有场景。


原文出处:/show_1GW3DNkMiZV2.html