
- TypeScript 基礎
- TypeScript - 首頁
- TypeScript - 路線圖
- TypeScript - 概述
- TypeScript - 環境設定
- TypeScript - 基本語法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 變數
- TypeScript - let & const
- TypeScript - 運算子
- TypeScript 基本型別
- TypeScript - 型別
- TypeScript - 型別註解
- TypeScript - 型別推斷
- TypeScript - 數字
- TypeScript - 字串
- TypeScript - 布林值
- TypeScript - 陣列
- TypeScript - 元組
- TypeScript - 列舉
- TypeScript - any
- TypeScript - never
- TypeScript - 聯合型別
- TypeScript - 字面量型別
- TypeScript - Symbols
- TypeScript - null vs. undefined
- TypeScript - 類型別名
- TypeScript 控制流
- TypeScript - 決策
- TypeScript - if 語句
- TypeScript - if else 語句
- TypeScript - 巢狀 if 語句
- TypeScript - switch 語句
- TypeScript - 迴圈
- TypeScript - for 迴圈
- TypeScript - while 迴圈
- TypeScript - do while 迴圈
- TypeScript 函式
- TypeScript - 函式
- TypeScript - 函式型別
- TypeScript - 可選引數
- TypeScript - 預設引數
- TypeScript - 匿名函式
- TypeScript - Function 建構函式
- TypeScript - rest 引數
- TypeScript - 引數解構
- TypeScript - 箭頭函式
- TypeScript 介面
- TypeScript - 介面
- TypeScript - 介面擴充套件
- TypeScript 類和物件
- TypeScript - 類
- TypeScript - 物件
- TypeScript - 訪問修飾符
- TypeScript - 只讀屬性
- TypeScript - 繼承
- TypeScript - 靜態方法和屬性
- TypeScript - 抽象類
- TypeScript - 存取器
- TypeScript - 鴨子型別
- TypeScript 高階型別
- TypeScript - 交叉型別
- TypeScript - 型別守衛
- TypeScript - 型別斷言
- TypeScript 型別操作
- TypeScript - 從型別建立型別
- TypeScript - keyof 型別運算子
- TypeScript - typeof 型別運算子
- TypeScript - 索引訪問型別
- TypeScript - 條件型別
- TypeScript - 對映型別
- TypeScript - 模板字面量型別
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型約束
- TypeScript - 泛型介面
- TypeScript - 泛型類
- TypeScript 其他
- TypeScript - 三斜槓指令
- TypeScript - 名稱空間
- TypeScript - 模組
- TypeScript - 環境宣告
- TypeScript - 裝飾器
- TypeScript - 型別相容性
- TypeScript - Date 物件
- TypeScript - 迭代器和生成器
- TypeScript - Mixins
- TypeScript - 實用程式型別
- TypeScript - 裝箱和拆箱
- TypeScript - tsconfig.json
- 從 JavaScript 到 TypeScript
- TypeScript 有用資源
- TypeScript - 快速指南
- TypeScript - 有用資源
- TypeScript - 討論
TypeScript - 泛型約束
在 TypeScript 中,泛型約束允許你指定對可與泛型型別引數一起使用的型別的限制。這透過確保泛型程式碼僅適用於相容的資料型別來增加一層型別安全。
問題示例
在深入研究泛型約束之前,讓我們瞭解需要應用泛型約束的問題示例。
示例
在下面的程式碼中,我們建立了merge()泛型函式,它將兩個物件作為引數,使用擴充套件運算符合並它們,並返回合併後的物件。
之後,我們透過傳遞兩個物件作為引數來呼叫merge()函式,它成功地列印了合併後的物件。
// Generic function to merge two objects function merge<T, U>(obj1: T, obj2: U) { return {...obj1, ...obj2}; } // Invoke the function const mergedObj = merge({name: 'Sam'}, {age: 30}); console.log(mergedObj); // Output: {name: 'Sam', age: 30}
編譯後,它將生成以下 JavaScript 程式碼。
// Generic function to merge two objects function merge(obj1, obj2) { return Object.assign(Object.assign({}, obj1), obj2); } // Invoke the function const mergedObj = merge({ name: 'Sam' }, { age: 30 }); console.log(mergedObj); // Output: {name: 'Sam', age: 30}
輸出
上面示例程式碼的輸出如下:
{name: 'Sam', age: 30}
merge()函式具有泛型引數。因此,它可以接受任何資料型別的數值作為引數,包括物件。如果你傳遞布林值作為第二個引數會怎樣?讓我們看看下面的例子。
示例
下面的示例程式碼與之前的程式碼非常相似。我們只是在呼叫時將merge()函式的第二個引數更改為布林值。
// Generic function to merge two objects function merge<T, U>(obj1: T, obj2: U) { return {...obj1, ...obj2}; } // Invoke the function const mergedObj = merge({name: 'Sam'}, true); console.log(mergedObj); // Output: {name: 'Sam'}
編譯後,它將生成以下 JavaScript 程式碼。
// Generic function to merge two objects function merge(obj1, obj2) { return Object.assign(Object.assign({}, obj1), obj2); } // Invoke the function const mergedObj = merge({ name: 'Sam' }, true); console.log(mergedObj); // Output: {name: 'Sam'}
輸出
上面示例程式碼的輸出如下:
{name: 'Sam'}
上面的程式碼只打印第一個物件,因為第二個引數是布林值而不是物件。為了解決上面示例程式碼中發現的問題,開發人員可以使用泛型約束。
TypeScript 中泛型約束的工作原理?
泛型約束允許我們將泛型引數限制為僅接受特定型別的數值。即你可以縮小泛型引數的型別。
語法
您可以按照以下語法使用泛型引數的泛型約束。
function merge<T extends object>(obj1: T) { // Code to execute }
在上面的語法中,“T”是一個泛型型別,“extends”是一個關鍵字,“object”是一個數據型別。
在這裡,“T”只接受具有“object”資料型別的數值。
讓我們透過下面的例子來更多地瞭解泛型約束。現在,如果你嘗試編譯下面的程式碼,你將得到編譯錯誤,因為泛型引數只能接受物件引數,但我們傳遞的是布林值。
// Generic function to merge two objects function merge<T extends object, U extends object>(obj1: T, obj2: U) { return { ...obj1, ...obj2 }; } // Invoke the function const mergedObj = merge({ name: 'Sam' }, true); console.log(mergedObj);
編譯上面的 TypeScript 程式碼時,編譯器會顯示以下錯誤:
Argument of type 'boolean' is not assignable to parameter of type 'object'.
這樣,我們可以限制泛型引數以接受特定資料型別的數值。
示例(使用介面擴充套件泛型型別)
讓我們逐步瞭解下面的程式碼。
我們定義了包含 name、age 和 email 屬性的“Person”介面。
接下來,我們定義了包含“empCode”和“empDept”屬性的“Employee”介面。
merge()函式包含兩個泛型引數 T(Person 型別)和 U(Employee 型別)。
在merge()函式中,我們合併兩個物件。
之後,我們分別定義了兩個 Person 和 Employee 型別的物件。
接下來,我們透過傳遞物件作為引數來呼叫merge()函式,程式碼執行沒有任何錯誤。
// Define Person interface interface Person { name: string; age: number; email: string; } // Define Employee interface interface Employee { empCode: number; empDept: string; } // Generic function which takes Objects of the Person and Employee interfaces types function merge<T extends Person, U extends Employee>(obj1: T, obj2: U) { return { ...obj1, ...obj2 }; } // Create two objects const person: Person = { name: 'John', age: 30, email: 'abc@gmail.com' }; const employee: Employee = { empCode: 1001, empDept: 'IT' }; // Invoke the function const mergedObj = merge(person, employee); console.log(mergedObj);
編譯後,它將生成以下 JavaScript 程式碼。
// Generic function which takes Objects of the Person and Employee interfaces types function merge(obj1, obj2) { return Object.assign(Object.assign({}, obj1), obj2); } // Create two objects const person = { name: 'John', age: 30, email: 'abc@gmail.com' }; const employee = { empCode: 1001, empDept: 'IT' }; // Invoke the function const mergedObj = merge(person, employee); console.log(mergedObj);
輸出
上面示例程式碼的輸出如下:
{ name: 'John', age: 30, email: 'abc@gmail.com', empCode: 1001, empDept: 'IT' }
在泛型約束中使用型別引數
TypeScript 還允許你定義一個型別引數,該引數受同一函式的另一個引數約束。
讓我們透過下面的例子來了解它。
示例
在下面的程式碼中,型別“U”擴充套件了在第一個引數中接收的物件的鍵。因此,它將接受obj物件的鍵作為引數,以避免函式體中的錯誤。
接下來,我們透過傳遞“obj”物件作為引數來呼叫getValue()函式。它在輸出中列印鍵值。
// Parameter U ensures that the key is a valid key of the object T. function getValue<T extends object, U extends keyof T>(obj: T, key: U) { return obj[key]; } // Define an object const obj = { name: 'Sam', age: 34 }; // Get the value of the key 'name' const name1 = getValue(obj, 'name'); console.log(name1); // Sam
編譯後,它將生成以下 JavaScript 程式碼。
// Parameter U ensures that the key is a valid key of the object T. function getValue(obj, key) { return obj[key]; } // Define an object const obj = { name: 'Sam', age: 34 }; // Get the value of the key 'name' const name1 = getValue(obj, 'name'); console.log(name1); // Sam
輸出
上面示例程式碼的輸出如下:
Sam
我們瞭解到泛型約束對於接受特定資料型別的數值作為引數而不是接受所有資料型別的數值很有用。