介绍
下面函数是 TypeScript 泛型函数 的基础代码,核心作用是:定义一个可以接收任意类型值、并保留类型信息的引用函数(对标 Vue3 中的 ref 响应式引用)。
// 定义一个泛型函数 myRef,T 是泛型类型参数
function myRef<T>(value: T) {
}
代码解释
逐行拆解:
function myRef:声明一个名为myRef的函数<T>:泛型类型参数(可以理解为「类型占位符」),T是自定义名称,也可以写成<Type>、<V>(value: T):函数参数value的类型 = 泛型T,传入什么类型的值,T就自动变成什么类型- 目前函数体为空
概念:什么是泛型?
用一句话解释:
泛型 = 不提前写死类型,让函数「复用逻辑 + 保留类型」,适用于任意数据类型。
对比普通函数 vs 泛型函数:
- 普通函数:只能固定一种类型(比如只能传数字/字符串)
- 泛型函数:传字符串 → 自动识别字符串类型;传对象 → 自动识别对象类型,类型不会丢失
应用场景
一般常见参数约束场景:不用泛型只能用 any,参数随便传、线上隐藏大量 bug。
使用泛型,会让函数调用更加安全:
- 约束数组每一项的统一类型
- 约束对象只能传合法 key
- 约束批量修改的字段不能乱传
- 约束回调函数的参数类型
例子1:通用数组处理
需求:遍历数组、打印每一项,只约束传入的数组元素类型
不用泛型(烂写法)
function printList(arr: any[]) {
arr.forEach(item => console.log(item))
}
// 胡乱传,完全不校验
printList([1, 2, 3])
printList(['a', 'b'])
printList([1, '哈哈', true]) // 混合类型也不报错
泛型写法(只约束参数)
// <T> 只用来约束 参数 arr 的成员类型
function printList<T>(arr: T[]) {
arr.forEach(item => console.log(item))
}
// 传入数字数组 → 参数强制只能是 number[]
printList<number>([1, 2, 3])
// printList<number>(['a', 2]) // ❌ 参数直接报错
// 传入字符串数组 → 参数强制只能是 string[]
printList<string>(['张三', '李四'])
✅ 关键点:
仅仅靠泛型约束「入参结构」,和返回值没有半点关系。
例子2:通用对象 key 取值(前端高频)
需求:传入一个对象、传入它的 key,约束 key 必须是对象身上合法属性
泛型参数版(纯参数约束)
// T 约束目标对象,K 约束对象的合法 key
function getObjKey<T, K extends keyof T>(obj: T, key: K) {
console.log(obj[key])
}
const user = { name: '小明', age: 18 }
getObjKey(user, 'name') // ✅ 参数合法
getObjKey(user, 'age') // ✅ 参数合法
getObjKey(user, 'sex') // ❌ 参数直接红线:user 没有 sex 属性
这里:
T约束第一个参数objK约束第二个参数key
全程只管入参合法性,函数内部只是打印,无返回值约束。
例子3:通用批量赋值函数
需求:给目标对象,批量修改字段,约束传入的修改字段必须匹配对象结构
function updateForm<T>(form: T, patch: Partial<T>) {
// 内部逻辑:合并赋值,不用管返回
Object.assign(form, patch)
}
const loginForm = {
username: '',
password: ''
}
// ✅ patch 参数只能是 username / password
updateForm(loginForm, { username: 'admin' })
// ❌ 报错:phone 不是表单合法字段
updateForm(loginForm, { phone: '111' })
核心:Partial<T> 只用来约束第二个入参,和返回值无关。
例子4:通用过滤函数(纯入参约束)
// 约束 list 数组元素类型
function filterList<T>(list: T[], filterFn: (item: T) => boolean) {
list.filter(filterFn)
}
// 数字数组 + 数字判断逻辑,参数强绑定
filterList<number>([10, 20, 30], (item) => item > 15)
// ❌ 第二个回调参数 item 会被锁死为 number,不能乱用字符串方法
filterList<number>([10, 20], (item) => item.includes('1'))
总结
<T>是泛型参数,代表「任意类型」,由传入值自动决定- 泛型函数 = 逻辑复用 + 类型保留
myRef<T>接收任意类型值,返回{ value: T }引用对象- 广泛用于响应式、状态管理、通用工具函数