TypeScript學習7:泛型

爲什麼引入泛型

如果說接口和類是對一類事物的抽象描述,那麼泛型可以說是對一類數據的抽象描述,進一步加強了語言的抽象程度,讓組件重用性更好。

看一個小例子,實現數組的單條數據插入:

function insertTo<T>(array: T[], index: number, t: T): T[] {
  if (index < 0 || array.length - 1 < index) {
    throw new Error('Illegal index.');
  }
  array.splice(index, 0, t);
  return array;
}

const arr1 = [1, 2, 4];
insertTo(arr1, 2, 3);
console.log(arr1);

const arr2 = ['a', 'b', 'd'];
insertTo(arr2, 2, 'c');
console.log(arr2);

這個函數使用了泛型來表示傳入參數的類型,我們可以很明顯感覺到泛型的好處:一個函數就可以適配多種類型。用普通方式,我們要重複這段邏輯寫n個函數,用泛型一個就夠用,這就是抽象的好處。

泛型的不同場景

泛型可以用於函數,也可以用於類,還有更高級的用法:帶限定的泛型。後面高級類型,還會用到泛型,會更復雜一些。

泛型函數

上面已給了一個例子,這裏再補充一個用法,限定類型的泛型函數:

interface GenericInsertFn<T> {
    <T>(array: T[], index: number, t: T): T[]
}

let myInsertTo: GenericInsertFn<number> = insertTo;

通過類型限定之後,我們就得到了一個新的函數,這個函數只能操作數字類型的數組。

泛型類

泛型類和泛型函數用法類似,只是泛型聲明在類上,整個類範圍都可以用。
看個小例子:

class MyArrayList<T> {
  private _array: T[];

  constructor() {
    this._array = [];
  }

  get lenght(): number {
    return this._array.length;
  }

  get(index: number): T {
    if (index < 0 || this._array.length - 1 < index) {
      throw new Error('Illegal index.');
    }
    return this._array[index];
  }

  push(...elements: T[]): number {
    return this._array.push(...elements);
  }

  insertTo(index: number, t: T): T[] {
    if (index < 0 || this._array.length - 1 < index) {
      throw new Error('Illegal index.');
    }
    this._array.splice(index, 0, t);
    return this._array;
  }
}

以上例子實現了一個簡單的泛型的ArrayList,如果你熟悉Java語言,對此就不陌生了。實現的效果和函數類似,也是抽象和重用。

泛型的限定

有的場景,泛型需要限定範圍,比如一個任務執行者函數,需要接受實現了工作者接口的函數作爲參數纔可以執行,那麼就需要帶限定的泛型參數,看代碼:

interface IWorker {
  (task: string): number; 
}

function excutor<W extends IWorker>(r: W) {
  r('case1');
}

const myWorker: IWorker = function (task: string) {
  console.log(`${task} is start.`);
  return 1;
}

excutor(myWorker);

再看一個更復雜一點的用法,多重泛型,抽象度也更高,通用性也更好。

interface IJobRunner<T, K> {
  run(t: T): K;
}

interface ITimeJobExcutor<T, K, R extends IJobRunner<T, K>> {
  excute(r: R): void;
}

基本的泛型用法學習完了,後面高級類型還會繼續學習更高級的用法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章