TypeScript泛型的使用詳細介紹
情景再現(xiàn)
這里針對一種情況,也是非常常見的一種情況:那就是
function identity(arg: number): number {
return arg;
}
就是我接收一個number類型的參數(shù),同時也返回一個number,那如果現(xiàn)在我想要接收一個string類型,同時也返回一個string,那么我就要再寫一個函數(shù)像這樣:
function identity2(arg: string): string{
return arg;
}
那如果我現(xiàn)在想要void類型…??????
可能大家會想,那全部都變成any不就行了?像下面這樣
function identity(arg: any): any {
return arg;
}
使用any類型會導致這個函數(shù)可以接收任何類型的arg參數(shù),這樣就丟失了一些信息:傳入的類型與返回的類型應該是相同的。 如果我們傳入一個數(shù)字,我們只知道任何類型的值都有可能被返回。
那這樣不就與我們一開始的設想不一致了嗎?我傳入Number,返回string,也不會報錯呀!??
因此,我們需要一種方法使返回值的類型與傳入?yún)?shù)的類型是相同的。 這里,我們使用了類型變量,它是一種特殊的變量,只用于表示類型而不是值。
function identity<T>(arg: T): T {
return arg;
}
我們給identity添加了類型變量T。 T幫助我們捕獲用戶傳入的類型(比如:number),之后我們就可以使用這個類型。 之后我們再次使用了T當做返回值類型?,F(xiàn)在我們可以知道參數(shù)類型與返回值類型是相同的了。 這允許我們跟蹤函數(shù)里使用的類型的信息。
????我們把這個版本的identity函數(shù)叫做泛型,因為它可以適用于多個類型。 不同于使用any,它不會丟失信息,像第一個例子那像保持準確性,傳入數(shù)值類型并返回數(shù)值類型。
使用泛型
第一種是,傳入所有的參數(shù),包含類型參數(shù)

第二種方法更普遍。利用了類型推論 – 即編譯器會根據(jù)傳入的參數(shù)自動地幫助我們確定T的類型
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString");
let output2 = identity("myString2");
console.log(output);
console.log(output2);

注意我們沒必要使用尖括號(<>)來明確地傳入類型;編譯器可以查看myString的值,然后把T設置為它的類型。 類型推論幫助我們保持代碼精簡和高可讀性。如果編譯器不能夠自動地推斷出類型的話,只能像上面那樣明確的傳入T的類型,在一些復雜的情況下,這是可能出現(xiàn)的。
泛型類型
我們研究一下函數(shù)本身的類型,以及如何創(chuàng)建泛型接口。
來看看泛型類型不同的展現(xiàn)方式:
function identity<T>(arg: T): T {
return arg;
}
let myFunction: <T>(arg:T) => T = identity;
我們也可以使用不同的泛型參數(shù)名,只要在數(shù)量上和使用方式上能對應上就可以。
function identity<T>(arg: T): T {
return arg;
}
let myFunction: <T>(arg:T) => T = identity;
let myIdentity: <U>(arg: U) => U = identity;
我們還可以使用帶有調(diào)用簽名的對象字面量來定義泛型函數(shù):
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: {<T>(arg: T): T} = identity;
是不是花了眼哈哈哈哈哈
泛型接口
還是以上面的為例子噢
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;可不可以詳細一點
一個相似的例子,我們可能想把泛型參數(shù)當作整個接口的一個參數(shù)。 這樣我們就能清楚的知道使用的具體是哪個泛型類型(比如:Dictionary< string>而不只是Dictionary)。 這樣接口里的其它成員也能知道這個參數(shù)的類型了。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;泛型類
我等這個泛型類等了好久好久??????
泛型類看上去與泛型接口差不多。 泛型類使用(<>)括起泛型類型,跟在類名后面。
// 泛型類
class GenericNumber<T> {
zeroValue: T | undefined;
add: ((x: T, y: T) => T) | undefined;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
function myAdd(x:number, y:number) {
return x + y;
};
myGenericNumber.add = function(x, y) {
return x + y;
};
console.log(myGenericNumber.add(1,2));
換string玩玩
// 泛型類
class GenericNumber<T> {
zeroValue: T | undefined;
add: ((x: T, y: T) => T) | undefined;
}
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "hi,";
stringNumeric.add = function(x, y) { return x + y; };
console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
也不是全能的
與接口一樣,直接把泛型類型放在類后面,可以幫助我們確認類的所有屬性都在使用相同的類型。
注意點??????類有兩部分:靜態(tài)部分和實例部分。 泛型類指的是實例部分的類型,所以類的靜態(tài)屬性不能使用這個泛型類型。
泛型約束
到底有沒有長度啊,救命
當我們使用泛型的時候,有這種情況:
我想要打印出傳過來的參數(shù)的長度為多少
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
這里會扯到一個問題,首先,你傳過來的這個玩意兒,它本身有長度嗎??
首先,什么樣的類型會有長度,毫無疑問,數(shù)組嘛
那我如果傳入的不是數(shù)組,那就鐵定報錯,就像上面那樣,正確的寫法大家也都懂:
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
相比于操作any所有類型,我們想要限制函數(shù)去處理任意帶有.length屬性的所有類型。 只要傳入的類型有這個屬性,我們就允許,就是說至少包含這一屬性。 為此,我們需要列出對于T的約束要求。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}現(xiàn)在傳入一個數(shù)字試試

傳入數(shù)組:
我們需要傳入符合約束類型的值,必須包含必須的屬性:

在泛型里使用類類型[]
在TypeScript使用泛型創(chuàng)建工廠函數(shù)時,需要引用構(gòu)造函數(shù)的類類型。
跟在Java中的很像——工廠模式,很是高級
function create<T>(c: {new(): T; }): T {
return new c();
}
高級案例
應用場景:傳入這個類,自動創(chuàng)建該類并且返回相應的屬性。
class BeeKeeper {
hasMask: boolean = false;
}
class ZooKeeper {
nametag:string = "ZooKeeper.nametag";
}
class Animal {
numLegs: number = 100;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
console.log(createInstance(Lion).keeper.nametag);
console.log(createInstance(Bee).keeper.hasMask);

到此這篇關(guān)于TypeScript泛型的使用詳細介紹的文章就介紹到這了,更多相關(guān)TypeScript泛型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)sleep睡眠函數(shù)的幾種簡單方法總結(jié)
sleep是一種函數(shù),他的作用是使程序暫停指定的時間,起到延時的效果,下面這篇文章主要給大家介紹了關(guān)于JavaScript實現(xiàn)sleep睡眠函數(shù)的幾種簡單方法總結(jié),文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-01-01
JavaScript面向?qū)ο蟮某绦蛟O計(犯迷糊的小羊)
這篇文章主要介紹了JavaScript面向?qū)ο蟮某绦蛟O計(犯迷糊的小羊),需要的朋友可以參考下2018-05-05
【JS+CSS3】實現(xiàn)帶預覽圖幻燈片效果的示例代碼
下面小編就為大家?guī)硪黄綣S+CSS3】實現(xiàn)帶預覽圖幻燈片效果的示例代碼。小編覺得挺不錯的,現(xiàn)在分享給大家。給大家一個參考2016-03-03
JavaScript數(shù)據(jù)結(jié)構(gòu)之棧實例用法
在本篇文章里小編給大家分享了關(guān)于JavaScript數(shù)據(jù)結(jié)構(gòu)之棧實例用法內(nèi)容,有興趣的朋友們學習下。2019-01-01
用javascript實現(xiàn)分割提取頁面所需內(nèi)容
用javascript實現(xiàn)分割提取頁面所需內(nèi)容...2007-05-05
帶領(lǐng)大家學習javascript基礎篇(一)之基本概念
這篇文章主要介紹了帶領(lǐng)大家學習javascript基礎篇(一)之基本概念的相關(guān)資料,需要的朋友可以參考下2015-11-11

