重学TypeScript --- 泛型

107 阅读2分钟

定义

在TypeScript中,泛型(Generics)允许我们在定义函数、类或接口时使用类型参数,以增强代码的灵活性和重用性。

function getVal<T>(value:T):T {
    return value
}
getVal<string>('字符串')
getVal<boolean>(true)
// 可以类型推断
getVal('字符串')
getVal(true)

泛型中的继承

写一个可以返回数值的length 属性的函数

// 此时的T 类似于 是一个type T = {} 一个空类型,是没有length 属性的,所以会报错
function getLength<T>(val:T):number {
    return val.length
}
// 当我们使用继承有length 属性的 类型就能解决这个问题
// 此时的T类似于 type T = {} & { length: number }
function getLength<T extends { length: number}>(val: T):number {
    return val.length
}
// 使用联合类型
function getLength<T extends string | any[]>(val: T):number {
    return val.length
}
// 可以限制数组的值为字符串
function getLength<T extends string | string[]>(val: T):number {
    return val.length
}
getLength('string') // 6
getLength(['1','2','3']) // 3
getLength(13) // 报错 number类型没有length属性

// 限制传入的参数为T 类型的数组
function getArrLength<T>(val:T[]):number {
    return val.length
}
getArrLength<string>(['1','2']) // 此时传递的数组的值只能为string
getArrLength<string | number>(['1','2',13])

泛型与类的结合

写一个集中管理数字的类

class collectionNumber {
    // 用数组来集中管理
    data:number[] = []
    // 用... 收集参数为数组
    public pushVal(...items:number[]) {
        this.data.push(...items)
    }
    // 返回data中的第一个值
    public showFirst():number {
        return this.data.shift()
    }
}
const numberCollection = new collectionNumber()
numberCollection.pushVal(1, 2, 3, 4, 5, 6)
console.log(numberCollection.showFirst()) // 返回1

那要是我们想要存储一个对象 类型,一个字符串类型的岂不是需要复制2次。 这个时候就可以使用泛型来代替这个操作

class collectionVal <T> {
    // 用数组来集中管理
    data:T[] = []
    // 用... 收集参数为数组
    public pushVal(...items:T[]) {
        this.data.push(...items)
    }
    // 返回data中的第一个值
    public showFirst():T {
        return this.data.shift()
    }
}
const stringCollection = new collectionVal<string>()
stringCollection.pushVal('string', '字符串')
console.log(stringCollection.showFirst()) // 返回 string

// 定义一个user 
type User = {
    name: string,
    age: number
}
const userCollection = new collectionVal<User>()
userCollection.pushVal({'小明', 18}, {'小红', 20})
console.log(userCollection.showFirst()) // 返回 {'小明', 18}

在接口中使用泛型

interface ArticleInterface <T, C> {
    title: string,
    isLook: T,
    comments: C[]
}
// 定义一个评论类型
interface commentType {
    content: string,
    userId: number,
    userName: string
}

const userComment: ArticleInterface<boolean, commentType> = {
    title: 'juejin',
    isLook: true,
    comments: [{content: '啊啊啊啊啊啊', userId: 123, userName: '张三' }]
}

const userComment2: ArticleInterface<number, commentType> = {
    title: 'juejin',
    isLook: 123,
    comments: [{content: '啦啦啦啦啦啦', userId: 456, userName: '李四' }]
}