TypeScript泛型


泛型的概念

指不預先確定的數據類型,具體的類型要在使用的時候才能確定。咋一聽,是不是覺得JavaScript本身就是這樣?這是由於理解有誤。前面說“在使用的時候確定”,而非在程序執行的時候確定。

泛型函數

現在有個需求:一個被定義的函數原本輸入字符串輸出字符串,現在想讓它同時支持輸入輸出字符串數組,如何實現?

1.通過函數重載

// 函數調用時依照聲明的順序進行匹配
function log(value: string): string; 
function log(value: string[]): string[];
 
function log(value: any): any{
    console.log(value);
    return value;
}
log("abc");
log(["10","abc"]);

2.使用聯合參數

function logs(value: string | string[]): string | string[]{
    return value
}

以上兩種都OK,但是不夠簡潔,不夠靈活。下面使用泛型。

function log1<T>(value: T): T{
    return value
}
等價於
let log1 = <T>(value: T) => {
    return value
};
log1<string>("hello");   // 調用的時候指定類型
log1<string[]>(["hi","ha"]);

泛型接口

// 要注意<T>的位置,前者在使用時必須指定類型,后者在使用時無須指定類型
interface Log<T> {
    (value: T): T;
}
let log3: Log<number> = (v) => { console.log("必須指定類型",v);return v };
log3(12);
 
interface Log{
    <T>(value: T): T;
}
let log3: Log = (v) => { console.log("無須指定類型",v);return v};
log3<number>(10); // 無須指定類型,如果要指定類型,在調用的時候指定
log3(5);

泛型類

對類的成員進行約束,注意不能約束靜態成員。

class Log<T> {
   run(value: T) {
      console.log(value);
      return value
   }
}
let log1 = new Log<number>(); // 可以進行約束
log1.run(1);
let log2 = new Log(); // 也可以不進行約束
log2.run("2");

泛型約束

泛型約束是指,傳入的參數必須符合約束,不符合約束的參數無法傳入。

function log<T>(value: T):T{
   console.log(value.length); // 如果訪問.length屬性,TS編譯器會報錯,因為不知道value有沒有這個屬性
   return value
}
此時使用泛型約束
interface Length {
   length: number;
   type?: string;
}
// extends Length表示允許value參數通過.操作符訪問Length中定義的屬性
function log<T extends Length>(value: T): T{
   console.log(value, value.length,value.type);
   return value
}
// 所有具有length屬性的值,都可以被當做參數傳入log函數
log([1,2,3]);
log("123");
log({length: 1});

在這個例子中,約束傳入的參數必須具有length屬性

使用泛型有什么好處?

  1. 函數和類可以支持多種類型,增強程序的擴展性。
  2. 不必寫多條函數重載、冗長的聯合類型聲明,增強代碼可讀性。
  3. 靈活控制類型之間的約束

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM