大家好,我是王天~ 這篇文章是 ts入門指南系列中第四篇,主要講解ts中的泛型應用,泛型在ts中是比較重要的概念,我花挺長時間才搞明白的,希望能幫助到大家 ~ ** ts 入門指南系列 ** Ts和Js 誰更適合前端開發?| typescript 入門指南 01 詳解tsconfig.json 配置 ...
大家好,我是王天~
這篇文章是 ts入門指南系列中第四篇,主要講解ts中的泛型應用,泛型在ts中是比較重要的概念,我花挺長時間才搞明白的,希望能幫助到大家 ~
** ts 入門指南系列 **
- Ts和Js 誰更適合前端開發?| typescript 入門指南 01
- 詳解tsconfig.json 配置文件 | 02 ts入門指南
- ts基礎使用-語法類型 | typescript入門指南 03
1. 前言
我們可以把泛型比喻為一個類型占位符,它告訴編譯器:“嘿,這裡有一個類型參數,我現在不確定具體是什麼類型,但稍後會告訴你。”
通過使用泛型,我們可以編寫更靈活、更可復用的代碼。它允許我們在定義函數、類或介面時使用類型占位符來表示類型,而不直接指定具體的類型。這樣,在實際使用時,我們可以傳入不同的類型參數,使得代碼可以適用於多種情況。
例如,讓我們看一個簡單的例子,來解釋泛型的使用。假設我們有一個名為 identity
的函數,它接受一個參數並返回該參數:
function identity<T>(value: T): T {
return value;
}
圖片來源網路
在上述代碼中,<T>
表示這是一個泛型函數,T
是一個類型參數,可以是任何類型。函數的參數 arg
的類型為 T
,返回值的類型也是 T
。
這樣,我們可以在函數調用時傳入不同的類型參數,使得函數適用於各種類型的參數。
例如,我們可以這樣調用 identity
函數:
let result1 = identity<number>(42); // 傳入 number 類型
let result2 = identity<string>("Hello, TypeScript"); // 傳入 string 類型
在第一次調用時,類型參數 number
被傳遞給 identity
函數,所以返回值的類型也是 number
。而在第二次調用時,類型參數 string
被傳遞給 identity
函數,所以返回值的類型是 string
。
通過使用泛型,我們可以編寫出更加通用的函數,不限於特定的類型。這樣一來,我們能夠避免代碼的重覆編寫,提高代碼的可復用性和靈活性。
泛型主要用在四個場合:函數、介面、類和別名。
基本使用
泛型使用尖括弧 <T>
來表示,併在定義函數、類或介面時指定類型參數。下麵是一些基本的使用示例:
// 示例1: 創建一個泛型函數
function identity<T>(arg: T): T {
return arg;
}
// 示例2: 使用泛型函數
let output = identity<string>("Hello");
console.log(output); // 輸出: Hello
// 示例3: 使用類型推斷,自動推斷泛型類型
let output2 = identity("Hello");
console.log(output2); // 輸出: Hello
在示例 1 中,函數 identity
使用了泛型類型參數 T
,表示參數和返回值的類型可以是任何類型。示例 2 和示例 3 展示瞭如何使用泛型函數並指定參數的類型。
。
2. 使用泛型變數:
泛型變數允許我們在函數或類中使用一種不確定的類型,而在實際使用時才確定具體的類型。
舉個例子,考慮一個簡單的函數identity
,它接受一個參數並返回相同的值:
function identity<T>(arg: T): T {
return arg;
}
在這個例子中,我們使用了泛型變數T
,它可以代表任意類型。當我們調用函數identity
時,編譯器會根據傳入的參數類型自動推斷T
的具體類型。
例如:
let result = identity<string>("Hello");
console.log(result); // 輸出:Hello
let value = identity<number>(42);
console.log(value); // 輸出:42
通過使用泛型變數,函數identity
可以適用於不同類型的參數,提供了更高的靈活性和可重用性。
3. 泛型類型:
泛型類型允許我們創建可以適用於不同類型的變數、函數或類。
舉個例子,考慮一個簡單的數組反轉函數reverse
:
function reverse<T>(array: T[]): T[] {
return array.reverse();
}
在這個例子中,我們定義了一個泛型函數reverse
,接受一個數組參數,並返回反轉後的數組。泛型類型T
用於指定數組的元素類型。
例如:
let numbers: number[] = [1, 2, 3, 4, 5];
let reversedNumbers = reverse(numbers);
console.log(reversedNumbers); // 輸出:[5, 4, 3, 2, 1]
let strings: string[] = ["apple", "banana", "orange"];
let reversedStrings = reverse(strings);
console.log(reversedStrings); // 輸出:["orange", "banana", "apple"]
通過使用泛型類型,函數reverse
可以適用於不同類型的數組,提供了更高的靈活性和可重用性。
4. 泛型類:
泛型類允許我們創建可以適用於多種類型的類。類中的成員可以使用泛型類型進行聲明和使用。
舉個例子,考慮一個簡單的Box
類,用於存儲任意類型的值:
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
在這個例子中,我們定義了一個泛型類Box
,它具有一個私有成員value
和一個公共方法getValue
用於獲取值。
例如:
let box1 = new Box<number>(42);
console.log(box1.getValue()); // 輸出:42
let box2 = new Box<string>("Hello");
console.log(box2.getValue()); // 輸出:Hello
過使用泛型參數<T>
,可以在類的定義中引入類型變數來表示未知的類型。這樣一來,我們可以在類實例化時指定具體的類型,從而創建適用於不同類型數據的類的實例。
5. 泛型約束:
泛型約束允許我們限制泛型類型的範圍,使其滿足特定條件
5.1. 確保屬性存在
舉個例子,假設我們想編寫一個函數getLength
,用於獲取對象的長度。但是並不是所有的對象都有length
屬性,所以我們需要對泛型類型進行約束,確保它具有該屬性。
例如:
interface HasLength {
length: number;
}
function getLength<T extends HasLength>(obj: T): number {
return obj.length;
}
在這個例子中,我們使用泛型約束T extends HasLength
來限制泛型類型T
必須滿足HasLength
介面的要求,即具有length
屬性。
例如:
let str = "Hello";
console.log(getLength(str)); // 輸出:5
let arr = [1, 2, 3, 4, 5];
console.log(getLength(arr)); // 輸出:5
通過使用泛型約束,函數getLength
可以接受具有length
屬性的對象,並返回其長度。
5.2 檢查對象的 key
1、keyof typescript 中檢測類型的方法,以聯合類型的方式方返回類型的所有 key
2、搭配泛型約、<T,K extends keyof T >
refshttps://juejin.cn/post/6844904184894980104#heading-0
使用泛型,可以讓我們在編譯前發現錯誤。
6 泛型介面:
泛型介面允許我們定義可以適用於不同類型的介面。
舉個例子,考慮一個簡單的Transformer
介面,它定義了一個將輸入值轉換為輸出值的轉換器:
interface Transformer<T, U> {
transform(input: T): U;
}
在這個例子中,我們定義了一個泛型介面Transformer
,它有兩個類型參數T
和U
,用於定義輸入類型和輸出類型。
例如,我們可以實現一個字元串到數字的轉換器:
class StringToNumberTransformer implements Transformer<string, number> {
transform(input: string): number {
return parseFloat(input);
}
}
通過定義實現了Transformer
介面的類,我們可以創建不同類型的轉換器。
例如:
let transformer = new StringToNumberTransformer();
let result = transformer.transform("3.14");
console.log(result); // 輸出:3.14
通過使用泛型介面,我們可以定義可重用、可靈活的介面,適用於不同類型的轉換操作。
介面搭配泛型,應用在 calss 類上
extend people 約束泛型類 在 people 介面範圍內
此時是 泛型變數占位符,在實例化 class 類是傳遞類型
interface people {
name: string;
age: number;
}
class Popele<T extends people> {
data: T;
constructor(data: T) {
this.data = data;
}
hi() {
return `${this.data.name},,${this.data.age}`;
}
}
let zhagnsan = new Popele<people>({ name: "張三", age: 18 });
總結
泛型在 TypeScript 中提供了更靈活、可重用的代碼編寫方式。它可以用於定義函數、類以及介面,讓我們能夠編寫適用於不同類型的代碼。
讀者朋友好呀,我是王天~
嘗試做過很多事情,汽修專業肄業生,半路出道的野生程式員、前端講師、新手作者,最終還是喜歡寫代碼、樂於用文字記錄熱衷分享~
如文章有錯誤或者不嚴謹的地方,期待給於指正,萬分感謝。
如果喜歡或者 有所啟發,歡迎 star,對作者也是一種鼓勵。
微信:「wangtian3111
」,加我進王天唯一的讀者群。