1.定义
泛型相当于一个类型变量,在定义时,无法预先知道具体的类型,可以用该变量来代替(占位),只有到调用时,才能确定它的类型。
很多时候,TS会智能的根据传递的参数,推导出泛型具体的类型。
如果无法完成推导,并且又没有传递具体的类型,默认为空对象。
2.在函数中使用泛型及泛型默认值
在函数名之后写上<泛型名称>
// 根据传入的个数,截取数组相应的值
// T 为占位符 即泛型
// 泛型也可以使用默认值
function getArr<T = string>(arr: T[], n: number): T[] {
if (n >= arr.length) return [...arr]
const newA: T[] = []
for (let i = 0; i < n; i++) {
newA.push(arr[i])
}
return newA
}
// 通过<>传递一个数字类型给T
const result = getArr<number>([1, 2, 3, 4], 2)
console.log(result);
3.在接口/类型别名上使用泛型
// 接口
// interface Callback<T> {
// (item: T, index: number): boolean
// }
// 类型别名
type Callback<T> = {
(item: T, index: number): boolean
}
function filter<T>(arr: T[], callback: Callback<T>): T[] {
const newA: T[] = []
arr.forEach((item, index) => {
if (callback(item, index)) {
newA.push(item)
}
})
return newA
}
const arr = [1, 2, 3, 4, 5]
const result = filter(arr, (item, index) => item % 2 === 0)
console.log(result); // [2,4]
4.泛型约束
通过泛型实现类型推断
// 传入一个对象,要求将对象的name属性的每个单词的首字母大写
interface hasNameProperty {
name: string
}
// 通过extends限制泛型T必须包含name属性
function nameToUpper<T extends hasNameProperty>(obj: T): T {
obj.name = obj.name.split(' ').map(s => {
return s[0].toUpperCase() + s.substr(1)
}).join(' ')
return obj
}
const obj = {
name: 'kan wan',
age: 12
}
const result = nameToUpper(obj)
console.log(result);
5.多泛型
当有多个参数的类型是未知时,可以通过多泛型来占位
// 传入两个数组,进行混合
// [1,2,3,4] + ['a','b','c','d'] = [1,'a',2,'b',3,'c',4,'d']
function mixinArr<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
if (arr1.length !== arr2.length) {
throw new Error('两个数组的长度不相等')
}
const newA: (T | K)[] = []
for (let i = 0; i < arr1.length; i++) {
newA.push(arr1[i])
newA.push(arr2[i])
}
return newA
}
const arr1 = [1, 2, 3, 4]
const arr2 = ['a', 'b', 'c', 'd']
const result = mixinArr(arr1, arr2)
console.log(result);