TypeScript-入门(八)-泛型

76 阅读2分钟

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);

image.png

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);