1. 程式人生 > 程式設計 >TypeScript 泛型的使用

TypeScript 泛型的使用

目錄
  • 1.簡單的使用
  • 2.在函式中使用泛型
  • 3.在類中使用泛型
  • 4.在泛型約束中使用型別引數

前言:

中,封裝一個API可以具有多種用途,因為其實弱型別語言,但是就因為是弱型別可以最終得到的結果並不是我們想要的。

TypeScript的出現正好中解決了這個問題,但是考慮到API的複用時,TypeScript又顯得不是這麼的靈活。這個時候可以使用any型別來解決不靈活的問題,但是又回到Script中的問題,得到最終的結果可能不是預期的那個樣子。

為了解決這種情況,TypeScript推出了泛型 的概念,使用泛型可以在定義函式、介面或類的時候,不預先指定具體的型別,而在使用的時候再指定型別,這樣做的目的是為了更大程度的來複用我們的程式碼。

1.簡單的使用

現在我們要定義一個join函式,該函式的功能主要是接受兩個型別一樣的值,返回兩個引數拼接後的值。示例程式碼如下:

// 所謂的泛型,通俗一點的解釋就是泛指的型別
// 定義一個join函式,接受兩個一樣型別的引數,並將兩個引數拼接後返回。
function join<T>(first: T,second: T) {
  return `${first}${second}`
}
// 這裡明確 T 為 string 型別
join<string>('第一','第二') // 第一第二
// 這裡通過型別推導的www.cppcns.com方式,編譯器會根據傳入的引數自動推斷出型別
join(1,2) // 12

定義泛型是通過<>對尖括號來定義,我們在定義join函式的時候,並不知道可以接受那些型別,但是可以明確的是兩個型別是必須一樣的,如果想要滿足這樣的需求,不用泛型的話解決起來是沒有這麼簡單的。

在呼叫函式的時候,這裡使用了兩種方式,一種是直接指定型別為string型別;另一種是通過型別推導的方式,編輯器會根據傳入的引數自動幫助我們確定型別。

2.在函式中使用泛型

在定義一個函式時,我們可以使用多個泛www.cppcns.com型,而且返回值型別也可以通過泛型指定,只要在數量上和使用方式上能對應就可以。

示例程式碼如下

function identity<T,Y,P>(first: T,second: Y,third: P): Y {
  return second
}
// 指定型別
identity<boolean,string,number>(true,'字串',12www.cppcns.com
3) // 字串 // 型別推斷 identity('string',123,true) // true

3.在類中使用泛型

我們不僅可以在函式中使用泛型,還可以在類中使用泛型。

示例程式碼如下:

class DataManager<T> {
  // 定義一個類,該類中具有一個T型別的私有陣列
  constructor(private data: T[]) {}
  // 根據索引說陣列中的值
  getItem(index: number): T {
    return this.data[index]
  }
}
const data = new DataManager(['一碗周'])
data.getItem(0) // 一碗周

而且泛型還可以繼承與於某個介面,示例程式碼如下:

interface Item {
  name: string
}
class DataManager<T extends Item> {
  // 定義一個類,該類中具有一個T型別的私有陣列
  constructor(private data: T[]) {}
  // 根據索引說陣列中的值
  getItem(index: number): string {
    return this.data[index].name
  }
}
const data = new DataManager([{ name: '一碗周' }])
data.getItem(0) // 一碗周

使用extends可以達到一個泛型約束 的作用,就上面那個程式碼來說,我們必須約束傳入的值必有具有一個name屬性,否則就會丟擲異常。

4.在泛型約束中使用型別引數

假如有如下需求,我們定義一個類,在類中一個私有物件,該物件中包含一些屬性;然後定義一個方法,通過key來獲取其對應的值。

實現程式碼如下:

// 定義一個介面
interface Person {
  name: string
  age: number
  hobby: string
}
// 定義一個類
class Me {
  constructor(private info: Person) {}
  getInfo(key: string) {
    return this.info[key]
  }
}
const me = new Me({
  name: '一碗周',age: 18,hobby: 'coding',})
// 呼叫 me.getInfo() 可能會得到一個 undefined 如下示例
me.getInfo('myName') // undefined

上面的程式碼,如果我們呼叫示例項物件中的getInfo()方法時,傳入一個沒有的屬性,會得到一個undefined。呼叫一個方法返回一個undefined時,這並不是TypeScript中的作風。

解決該問題可以通過keyof操作符,該關鍵字可以通過該操作符可以用於獲取某種型別的所有鍵,其返回型別是聯合型別。

示例程式碼如下:

type myPerson = keyof Person // 'name' | 'age' | 'hobby'

那現在就可以通過該操作符解決上面出現的那個問題

示例程式碼如下:

class Me {
  constructor(private info: Person) {}
  // 該寫法與如下寫法是一樣的
  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key]
  }
  // getInfo<T extends 'name' | 'age' | 'hobby'>(key: T): Person[T] {
  //     return this.info[eLABGpPkey]
  // }
}
const me = new Me({
  name: '一碗周',})
// 呼叫 me.getInfo() 如果傳遞一個未知的屬性則會編譯錯誤
me.getInfo('myName') // error : 型別“"myName"”的引數不能賦給型別“keyof Person”的引數。

現在我們只要訪問物件中不具有的屬性編譯則會異常。

到此這篇關於TypeScript 泛型的使用的文章就介紹到這了,更多相關TypeScript 泛型內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!