指在定義函數(shù)殴蹄、接口或類的時(shí)候,不預(yù)先指定具體的類型猾担,而在使用的時(shí)候再指定具體類型的一種特性袭灯。
引入
下面創(chuàng)建一個(gè)函數(shù), 實(shí)現(xiàn)功能: 根據(jù)指定的數(shù)量 count 和數(shù)據(jù) value , 創(chuàng)建一個(gè)包含 count 個(gè) value 的數(shù)組 不用泛型的話,這個(gè)函數(shù)可能是下面這樣:
function createArray(value: any, count: number): any[] {
const arr: any[] = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr1 = createArray(11, 3)
const arr2 = createArray('aa', 3)
console.log(arr1[0].toFixed(), arr2[0].split(''))
使用函數(shù)泛型
function createArray2 <T> (value: T, count: number) {
const arr: Array<T> = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr3 = createArray2<number>(11, 3)
console.log(arr3[0].toFixed())
// console.log(arr3[0].split('')) // error
const arr4 = createArray2<string>('aa', 3)
console.log(arr4[0].split(''))
// console.log(arr4[0].toFixed()) // error
多個(gè)泛型參數(shù)的函數(shù)
一個(gè)函數(shù)可以定義多個(gè)泛型參數(shù)
function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())
泛型接口
在定義接口時(shí), 為接口中的屬性或方法定義泛型類型
在使用接口時(shí), 再指定具體的泛型類型
interface IbaseCRUD <T> {
data: T[]
add: (t: T) => void
getById: (id: number) => T
}
class User {
id?: number; //id主鍵自增
name: string; //姓名
age: number; //年齡
constructor (name, age) {
this.name = name
this.age = age
}
}
class UserCRUD implements IbaseCRUD <User> {
data: User[] = []
add(user: User): void {
user = {...user, id: Date.now()}
this.data.push(user)
console.log('保存user', user.id)
}
getById(id: number): User {
return this.data.find(item => item.id===id)
}
}
const userCRUD = new UserCRUD()
userCRUD.add(new User('tom', 12))
userCRUD.add(new User('tom2', 13))
console.log(userCRUD.data)
泛型類
在定義類時(shí), 為類中的屬性或方法定義泛型類型 在創(chuàng)建類的實(shí)例時(shí), 再指定特定的泛型類型
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
return x + y
}
let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) {
return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))
泛型約束
如果我們直接對(duì)一個(gè)泛型參數(shù)取 length
屬性, 會(huì)報(bào)錯(cuò), 因?yàn)檫@個(gè)泛型根本就不知道它有這個(gè)屬性
// 沒有泛型約束
function fn <T>(x: T): void {
// console.log(x.length) // error
}
我們可以使用泛型約束來(lái)實(shí)現(xiàn)
interface Lengthwise {
length: number;
}
// 指定泛型約束
function fn2 <T extends Lengthwise>(x: T): void {
console.log(x.length)
}
我們需要傳入符合約束類型的值绑嘹,必須包含必須 length 屬性:
fn2('abc')
// fn2(123) // error number沒有l(wèi)ength屬性