TypeScript基礎(二)泛型的應用
theme: channing-cyan
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第4天,點擊查看活動詳情
泛型函數
泛型: 是指在定義函數、接口或類的時候,不預先指定具體的類型,而在使用的時候再指定類型的一種特性。
定義泛型函數
正常聲明一個變量的時候,像是下面這樣。
ts
const a: string = "kong";
而泛型,是在使用的時候才會指定類型(一般用大寫的T
做變量,Type的簡寫,用其他的也都沒問題),如下:
ts
function fn1<T>(value: T): T {
return value;
}
fn1<string>("kong");
fn1(1);
上面的函數fn1
添加了類型變量 T
,T
能夠捕獲到用户傳入的參數類型,然後再根據T
做函數返回值的類型。
調用的時候可以<>
手動設定類型,也可以不設置讓ts自動進行類型推導。
- 默認類型
聲明函數的時候,可以傳給T
一個默認類型。調用函數的時候,不傳遞類型就是默認類型。
ts
function fn1<T = number>(value: T): T {
return value;
}
- 多個類型參數
定義泛型的時候,可以一次性定義多個類型參數
ts
function swap<T, U>(arr: [T, U]): [U, T] {
return [arr[1], arr[0]]
}
swap([100, "haha"]); // ["haha", 100]
類型約束
在函數內部使用泛型的變量的時候,由於還不知道它屬於哪種類型,所以不能隨意操作變量的屬性和方法。
如下: value.length
會出現錯誤信息 類型T上不存在屬性length
ts
function fn2<T>(value: T){
value.length // 錯誤:類型T上不存在屬性length
}
這時候就可以使用 類型約束,關鍵字 extends
。
```ts interface HasLength { length: number }
function fn3
上述代碼,讓泛型T
繼承自Haslength
接口,表明傳入的參數要遵守 HasLength
接口的規則,也就是必須要含有length
屬性。
也可以直接這樣繼承:
ts
function fn3<T extends {length: number}>(value: T) {
value.length
}
此時,如果傳入不包含length
屬性的參數,就會在編譯階段提示錯誤:
ts
fn3([1,2,3]); // 正確
fn3("KONG"); // 正確
fn3(100); // 錯誤
提示錯誤: 類型number的參數不能賦值給類型HasLength的參數。
使用泛型編寫一個好的函數要注意的點
- 可能的情況下,使用類型參數本身,而不是對其進行約束
- 儘可能少的使用類型參數
- 如果一個類型的參數只出現在一個地方,請重新考慮是否真的需要它
泛型接口
定義一個標準的接口,應該像下面這樣:
ts
interface Person {
name: string,
age: number
}
const p1: Person = {
name: "tom",
age: 18
}
- 簡單使用
上面接口裏面的類型是固定寫死的,如果需要由用户傳入接口的類型,那就需要使用泛型來定義接口:
ts
interface Person2<T1, T2> {
name: T1,
age: T2,
}
const p2: Person2<string, number> = {
name: "jack",
age: 18
}
上面的例子是在使用的時候傳入了類型,也可以在定義接口的時候給泛型默認值:
ts
interface Person2<T1 = string, T2 = number> {
name: T1,
age: T2,
}
- 使用泛型接口的方式定義函數需要符合的形狀
```ts
interface CreateArr {
let createArrFn: CreateArr;
createArrFn = function ``
上面的接口,使用泛型定義了一個函數。然後創建了
createArrFn方法,實現了這個泛型接口的函數。可以傳入兩個參數
length和
value,其中
length為數組的長度所以是
number類型,
value類型為泛型,根據調用方法時傳入參數的類型決定。最終這個方法會返回一個長度為
length`的數組。
泛型類
- 在類名後面定義泛型
T
,類裏面使用
ts
class GenAny<T> {
value: T;
add: (x: T, y: T) => T;
}
ts
const myGen = new GenAny<number>();
myGen.value = 100;
myGen.add = (x, y) => x + y;
// 調用
myGen.add(3, 4);
- 應用: 定義一個
Person
類
ts
class Person<T1, T2> {
name: T1;
age: T2;
sex: T1;
constructor(name: T1, age: T2, sex: T1){
this.name = name;
this.age = age;
this.sex = sex;
}
}
上面的Person
類包含了泛型T1
T2
,name age sex
屬性。
實例化:
- 自動類型推導,可以不傳入參數的類型:
ts
const p1 = new Person("tom", 18, "boy");
自動推斷出T1
為string
類型,T2
為 number
類型。此時如果第三個參數sex傳入非string類型就會提示錯誤,以為已經把T1
自動推導為string
類型了。
-
不用類型推導就要在
new
實例化的時候傳入類型ts const p2 = new Person<string, string>("jack", "18", "boy");
-
使用類來約束對象並傳遞類型
ts const p3: Person<string, number> = new Person("jack", 18, "boy");
這時候可以發現上一節中用Array
類來聲明數組的寫法和使用泛型類約束變量的寫法是很相似的:
ts
const arr: Array<number> = [2, 4, 6];
- 騰訊雲微服務引擎 TSE 產品動態
- 我們被一個 kong 的性能 bug 折騰了一個通宵
- 我們被一個 kong 的性能 bug 折騰了一個通宵
- 我們被一個 kong 的性能 bug 折騰了一個通宵
- Pulumi 到底比 Terraform 強在哪
- TypeScript基礎(二)泛型的應用
- vue3組件化開發之可複用性的應用
- vue3組件化開發常用API
- PAM 2022 論文錄用列表
- 開工第一天,這個超時問題把我幹趴下了
- 流利説業務網關Kong K8s化之路
- Kong 優雅實現微服務網關鑑權,登錄場景落地實戰篇
- 技術耦合、行業相融,中國樓宇自控行業將走出新方向
- API 網關 Kong 實戰
- Kong解碼gzip body
- Docker安裝Kong API Gateway並使用
- Kong常用plugin-03-Rate Limiting
- Kong常用plugin-02-Basic Auth
- Kong網關集羣方案
- Kong Go Plugin 方式2:動態擴展庫so加載