初識泛型
如果我們想寫一個(gè)函數(shù),它的參數(shù)和返回值類型相同,首先我們會想到下面這種寫法:
function getNum(num: number): number{
return num;
}
function getStr(str: string): string{
return str;
}
或者使用any來定義類型:
function getItem(arg: any): any{
return arg;
}
但是使用any類型會導(dǎo)致我們無法保證參數(shù)類型與返回的類型一定是相同的。所以我們可以采用下面這種方式:
function identity<T>(arg: T): T{
return arg;
}
我們在函數(shù)名稱后面聲明變量<T>,它用于捕獲開發(fā)者傳入的參數(shù)類型,然后我們就可以使用T做參數(shù)類型和返回值類型了。
泛型變量
現(xiàn)在假設(shè)我們想操作T類型的數(shù)組而不直接是T:
function getArr<T>(arg: T[]): T[]{
return arg;
}
console.log(getArr([1,2])); //[1,2]
這里我們傳入的是數(shù)字?jǐn)?shù)組,將返回一個(gè)數(shù)字?jǐn)?shù)組,因?yàn)榇藭r(shí)T的的類型為number。 這時(shí)我們把泛型變量T當(dāng)做類型的一部分使用,而不是整個(gè)類型。
泛型接口
interface GenericFn<T>{
(arg: T): T
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericFn<number> = identity;
// let myIdentity: GenericFn<number> = num=>num;
泛型類
class MyArr<T> {
arr: T[] = [];
push(num: T) {
this.arr.push(num)
}
}
let a = new MyArr<number>();
a.push(10);
泛型約束
type Params = number | undefined;
class MyArr<T extends Params> {
arr: T[] = [];
push(num: T) {
this.arr.push(num)
}
}
let a1 = new MyArr<number>();
let a2= new MyArr<string>(); //類型“string”不滿足約束“Params”
索引類型
function getValue(obj: object, key: string) {
return obj[key]
}

image.png
function getValue<T extends object, U extends keyof T>(obj: T, key: U) {
return obj[key];
}
我們用索引類型keyof T把傳入的對象的屬性類型取出生成一個(gè)聯(lián)合類型,這里的泛型 U 被約束在這個(gè)聯(lián)合類型中。