若是說接口和類是對一類事物的抽象描述,那麼泛型能夠說是對一類數據的抽象描述,進一步增強了語言的抽象程度,讓組件重用性更好。 typescript
看一個小例子,實現數組的單條數據插入:數組
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個函數,用泛型一個就夠用,這就是抽象的好處。函數
泛型能夠用於函數,也能夠用於類,還有更高級的用法:帶限定的泛型。後面高級類型,還會用到泛型,會更復雜一些。學習
上面已給了一個例子,這裏再補充一個用法,限定類型的泛型函數:this
interface GenericInsertFn<T> { <T>(array: T[], index: number, t: T): T[] } let myInsertTo: GenericInsertFn<number> = insertTo;
經過類型限定以後,咱們就獲得了一個新的函數,這個函數只能操做數字類型的數組。code
泛型類和泛型函數用法相似,只是泛型聲明在類上,整個類範圍均可以用。
看個小例子:接口
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語言,對此就不陌生了。實現的效果和函數相似,也是抽象和重用。ip
有的場景,泛型須要限定範圍,好比一個任務執行者函數,須要接受實現了工做者接口的函數做爲參數才能夠執行,那麼就須要帶限定的泛型參數,看代碼:element
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);
再看一個更復雜一點的用法,多重泛型,抽象度也更高,通用性也更好。get
interface IJobRunner<T, K> { run(t: T): K; } interface ITimeJobExcutor<T, K, R extends IJobRunner<T, K>> { excute(r: R): void; }
基本的泛型用法學習完了,後面高級類型還會繼續學習更高級的用法。