TypeScript - 泛型



泛型是 TypeScript 中一個強大的特性,它允許您編寫可重用的程式碼,這些程式碼可以處理不同型別的資料。它們充當佔位符,當您使用泛型程式碼時,可以用特定的資料型別填充這些佔位符。這提高了程式碼的靈活性以及可維護性。

問題示例

在深入瞭解 TypeScript 泛型之前,讓我們先了解一下需要應用泛型的問題示例。

讓我們從下面的示例開始,您希望記錄作為引數傳遞的變數的值。

示例

在下面的程式碼中,我們定義了 printVar() 函式,該函式將數字值作為引數並將其值記錄到控制檯。接下來,我們透過傳遞 10 作為引數來呼叫該函式。

function printVar(val: number) {
    console.log(val); // Prints the value of val
}
printVar(10); // Invokes the function with a number

編譯後,它將生成以下 JavaScript 程式碼。

function printVar(val) {
    console.log(val); // Prints the value of val
}
printVar(10); // Invokes the function with a number

輸出

其輸出如下所示:

10

現在,假設您希望擴充套件 printVar() 函式的使用案例,以列印其他型別變數(如字串、布林值等)的值。一種方法如下面的示例所示。

示例

在下面的程式碼中,printVar() 函式可以接受數字、字串或布林型別的引數。

function printVar(val: number | string | boolean) {
    console.log(val); // Prints the value of val
}
printVar(true); // Invokes the function with a boolean value

編譯後,它將生成以下 JavaScript 程式碼。

function printVar(val) {
    console.log(val); // Prints the value of val
}
printVar(true); // Invokes the function with a boolean value

輸出

輸出如下所示:

true

如果要列印陣列或物件值怎麼辦?您需要擴充套件“val”引數的型別,這使得程式碼難以閱讀。

另一種使用“any”資料型別引數的方法如下面的示例所示。

示例

在下面的程式碼中,“val”引數的型別為 any。因此,它可以接受任何型別的引數。

function printVar(val: any) {
    console.log(val); // Prints the value of val
}
printVar("Hello world!"); // Invokes the function with a boolean value

編譯後,它將生成以下 JavaScript 程式碼:

function printVar(val) {
    console.log(val); // Prints the value of val
}
printVar("Hello world!"); // Invokes the function with a boolean value

輸出

其輸出如下所示:

Hello world!

上面程式碼的問題在於,您在函式內部將無法引用資料型別。無論您將字串、數字、布林值、陣列等作為函式引數傳遞,在函式中都將獲得變數的“any”型別。

這裡,泛型函式就派上用場了。

TypeScript 泛型

在 TypeScript 中,泛型是一個允許建立可重用元件(如函式、類、介面等)的概念。它建立了一個可以處理多種資料型別而不是單個數據型別的函式、類等。簡而言之,它允許開發人員建立可以處理多種資料型別的程式,並且從長遠來看是可擴充套件的。

語法

使用者可以按照以下語法在 TypeScript 中使用泛型變數與函式。

function printVar<T>(val: T) {
    // execute the code
}
printVar(val);
  • 開發人員可以在函式名後使用尖括號(<>)中的型別變數。

  • 之後,您可以使用型別變數 T 作為引數的型別。

  • 這裡,開發人員可以使用任何有效的識別符號代替“T”。

  • 之後,您可以使用任何資料型別的呼叫函式,並且函式會自動捕獲變數的資料型別。

示例

在下面的示例中,printVar() 函式是一個泛型函式,它將任何資料型別的作為引數,並列印它。

之後,我們使用陣列、物件和布林值呼叫了該函式。在輸出中,使用者可以觀察到它在沒有任何錯誤的情況下列印了不同型別變數的值。

function printVar<T>(val: T) { // T is a generic type
    console.log("data: ", val);
}
let arr = [1, 2, 3];
let obj = { name: "John", age: 25 };

printVar(arr); // Val is array
printVar(obj); // Val is Object
printVar(true); // Val is boolean

編譯後,它將生成以下 JavaScript 程式碼。

function printVar(val) {
    console.log("data: ", val);
}
let arr = [1, 2, 3];
let obj = { name: "John", age: 25 };
printVar(arr); // Val is array
printVar(obj); // Val is Object
printVar(true); // Val is boolean

輸出

上面示例程式碼的輸出如下:

data:  [ 1, 2, 3 ]
data:  { name: 'John', age: 25 }
data:  true

示例

在此程式碼中,printVar() 函式是一個泛型函式,它獲取作為引數傳遞的變數值的型別。在呼叫該函式時,我們傳遞了不同資料型別的值,使用者可以在輸出中觀察到每個變數的型別。

function printVar<T>(val: T) { // T is a generic type
    console.log("data: ", typeof val);
}

printVar(2); // Val is number
printVar("Hello"); // Val is string
printVar(true); // Val is boolean

編譯後,它將生成以下 JavaScript 程式碼。

function printVar(val) {
    console.log("data: ", typeof val);
}
printVar(2); // Val is number
printVar("Hello"); // Val is string
printVar(true); // Val is boolean

輸出

上面示例程式碼的輸出如下:

data:  number
data:  string
data:  boolean

示例

在下面的程式碼中,concatenate() 函式分別採用型別為 TU 的兩個引數。它使用擴充套件運算子連線“first”和“second”引數的值。

接下來,我們呼叫該函式以連線兩個字串和陣列。在輸出中,我們可以看到 concatenate() 函式在沒有任何錯誤的情況下執行,並在控制檯中列印最終輸出。

function concatenate<T, U>(first: T, second: U): T & U {
    return {...first, ...second};
}

// Example usage with strings
const resultString = concatenate("Hello, ", "world!");
console.log(resultString); // Output: Hello, world!

// Example usage with arrays
const resultArray = concatenate([1, 2, 3], [4, 5, 6]);
console.log(resultArray); // Output: [1, 2, 3, 4, 5, 6]

編譯後,它將生成以下 JavaScript 程式碼。

function concatenate(first, second) {
    return Object.assign(Object.assign({}, first), second);
}
// Example usage with strings
const resultString = concatenate("Hello, ", "world!");
console.log(resultString); // Output: Hello, world!
// Example usage with arrays
const resultArray = concatenate([1, 2, 3], [4, 5, 6]);
console.log(resultArray); // Output: [1, 2, 3, 4, 5, 6]

輸出

上面示例程式碼的輸出如下:

{
  '0': 'w',
  '1': 'o',
  '2': 'r',
  '3': 'l',
  '4': 'd',
  '5': '!',
  '6': ' '
}
{ '0': 4, '1': 5, '2': 6 }

泛型的優勢

以下是 TypeScript 中使用泛型的一些優勢。

  • 型別安全:泛型強制執行型別一致性,透過在編譯時捕獲錯誤來減少執行時錯誤。

  • 程式碼可重用性:開發人員可以定義單個泛型函式、類或介面,這些函式、類或介面可以處理不同的資料型別。它減少了程式碼重複。

  • 提高可讀性:透過使用泛型,開發人員可以編寫更簡潔、更易於閱讀的程式碼。

  • 增強效能:您可以透過避免不必要的型別轉換和檢查來提高應用程式的效能,方法是使用泛型。

廣告